about summary refs log tree commit diff stats
path: root/miasm2/jitter
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/jitter')
-rw-r--r--miasm2/jitter/Jitllvm.c36
-rw-r--r--miasm2/jitter/Jittcc.c226
-rw-r--r--miasm2/jitter/Makefile17
-rw-r--r--miasm2/jitter/__init__.py0
-rw-r--r--miasm2/jitter/arch/JitCore.h66
-rw-r--r--miasm2/jitter/arch/JitCore_arm.c388
-rw-r--r--miasm2/jitter/arch/JitCore_arm.h147
-rw-r--r--miasm2/jitter/arch/JitCore_msp430.c694
-rw-r--r--miasm2/jitter/arch/JitCore_msp430.h171
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c873
-rw-r--r--miasm2/jitter/arch/JitCore_x86.h293
-rw-r--r--miasm2/jitter/arch/__init__.py0
-rw-r--r--miasm2/jitter/csts.py22
-rw-r--r--miasm2/jitter/jitcore.py252
-rw-r--r--miasm2/jitter/jitcore_llvm.py157
-rw-r--r--miasm2/jitter/jitcore_tcc.py146
-rw-r--r--miasm2/jitter/jitload.py1089
-rw-r--r--miasm2/jitter/llvmconvert.py982
-rw-r--r--miasm2/jitter/os_dep/__init__.py0
-rw-r--r--miasm2/jitter/os_dep/linux_stdlib.py78
-rw-r--r--miasm2/jitter/os_dep/win_api_x86_32.py3069
-rw-r--r--miasm2/jitter/os_dep/win_api_x86_32_seh.py896
-rw-r--r--miasm2/jitter/queue.h553
-rw-r--r--miasm2/jitter/vm_mngr.c1640
-rw-r--r--miasm2/jitter/vm_mngr.h363
-rw-r--r--miasm2/jitter/vm_mngr_py.c939
26 files changed, 13097 insertions, 0 deletions
diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c
new file mode 100644
index 00000000..ab077b05
--- /dev/null
+++ b/miasm2/jitter/Jitllvm.c
@@ -0,0 +1,36 @@
+#include <Python.h>
+
+#include <inttypes.h>
+
+#include <stdint.h>
+
+PyObject* llvm_exec_bloc(PyObject* self, PyObject* args)
+{
+	uint64_t (*func)(void*, void*);
+	uint64_t vm;
+	uint64_t cpu;
+	uint64_t ret;
+
+	if (!PyArg_ParseTuple(args, "KKK", &func, &cpu, &vm))
+		return NULL;
+	ret = func((void*)cpu, (void*)vm);
+	return PyLong_FromUnsignedLongLong( (uint64_t)ret);
+}
+
+
+static PyMethodDef LLVMMethods[] = {
+    {"llvm_exec_bloc",  llvm_exec_bloc, METH_VARARGS,
+     "llvm exec bloc"},
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+
+PyMODINIT_FUNC
+initJitllvm(void)
+{
+    PyObject *m;
+
+    m = Py_InitModule("Jitllvm", LLVMMethods);
+    if (m == NULL)
+	    return;
+
+}
diff --git a/miasm2/jitter/Jittcc.c b/miasm2/jitter/Jittcc.c
new file mode 100644
index 00000000..4b16f0b1
--- /dev/null
+++ b/miasm2/jitter/Jittcc.c
@@ -0,0 +1,226 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+
+#include <inttypes.h>
+#include <libtcc.h>
+
+#include <stdint.h>
+
+
+
+/* tcc global state */
+TCCState *tcc_state = NULL;
+
+
+int include_array_count = 0;
+char **include_array = NULL;
+
+
+int lib_array_count = 0;
+char **lib_array = NULL;
+
+//char *libcodenat_path = NULL;
+
+
+void tcc_init_state(void)
+{
+	int i;
+
+	tcc_state = tcc_new();
+	if (!tcc_state) {
+		fprintf(stderr, "Impossible de creer un contexte TCC\n");
+		exit(1);
+	}
+	tcc_set_output_type(tcc_state, TCC_OUTPUT_MEMORY);
+
+	//tcc_add_file(tcc_state, libcodenat_path);
+	for (i=0;i<lib_array_count; i++){
+		tcc_add_file(tcc_state, lib_array[i]);
+	}
+
+	for (i=0;i<include_array_count; i++){
+		tcc_add_include_path(tcc_state, include_array[i]);
+	}
+}
+
+
+
+
+PyObject* tcc_set_emul_lib_path(PyObject* self, PyObject* args)
+{
+	char* include_arg;
+	char* lib_arg;
+
+	char* str1, * str2;
+
+	if (!PyArg_ParseTuple(args, "ss",
+			      &include_arg,
+			      &lib_arg))
+		return NULL;
+	/*
+	if (include_array)
+		free(include_array);
+	*/
+
+	str2 = strdup(include_arg);
+	while (str2){
+		str1 = strsep(&str2, ";");
+		if (str1){
+			include_array_count ++;
+			include_array = realloc(include_array,
+						     include_array_count * sizeof(char*));
+			include_array[include_array_count-1] = strdup(str1);
+			fprintf(stderr, "adding include file: %s\n", str1);
+		}
+	}
+
+
+	str2 = strdup(lib_arg);
+	while (str2){
+		str1 = strsep(&str2, ";");
+		if (str1){
+			lib_array_count ++;
+			lib_array = realloc(lib_array,
+						 lib_array_count * sizeof(char*));
+			lib_array[lib_array_count-1] = strdup(str1);
+			fprintf(stderr, "adding lib file: %s\n", str1);
+		}
+	}
+
+	/*
+	libcodenat_path = (char*)malloc(strlen(libcodenat_path_arg)+1);
+	strcpy(libcodenat_path, libcodenat_path_arg);
+	*/
+	Py_INCREF(Py_None);
+
+
+	return Py_None;
+}
+
+
+PyObject* tcc_exec_bloc(PyObject* self, PyObject* args)
+{
+	PyObject* (*func)(void*, void*);
+	uint64_t vm;
+	uint64_t cpu;
+	PyObject* ret;
+
+	if (!PyArg_ParseTuple(args, "KKK", &func, &cpu, &vm))
+		return NULL;
+	ret = func((void*)cpu, (void*)vm);
+	return ret;
+}
+
+PyObject* tcc_compil(PyObject* self, PyObject* args)
+{
+	char* func_name;
+	char* func_code;
+	int (*entry)(void);
+
+	tcc_init_state();
+
+	if (!PyArg_ParseTuple(args, "ss", &func_name, &func_code))
+		return NULL;
+
+	if (tcc_compile_string(tcc_state, func_code) != 0) {
+		fprintf(stderr, "Erreur de compilation !\n");
+		fprintf(stderr, "%s\n", func_code);
+		exit(0);
+	}
+	/* XXX use tinycc devel with -fPIC patch in makefile */
+	if (tcc_relocate(tcc_state, TCC_RELOCATE_AUTO) < 0) {
+		fprintf(stderr, "tcc relocate error\n");
+		exit(0);
+	}
+	entry = tcc_get_symbol(tcc_state, func_name);
+	if (!entry){
+		fprintf(stderr, "Erreur de symbole %s!\n", func_name);
+		fprintf(stderr, "%s\n", func_name);
+		exit(0);
+	}
+	return PyLong_FromUnsignedLongLong((uint64_t)entry);
+
+}
+
+
+
+PyObject* tcc_loop_exec(PyObject* self, PyObject* args)
+{
+	//PyObject* (*func)(void*, void*);
+	uint64_t* vm;
+	uint64_t* cpu;
+	PyObject* ret;
+	PyObject* func;
+	PyObject* pArgs;
+
+
+	if (!PyArg_ParseTuple(args, "OKK", &func, &cpu, &vm))
+		return NULL;
+
+	while (1) {
+		if (!PyCallable_Check (func)) {
+			fprintf(stderr, "function not callable!\n");
+			exit(0);
+		}
+
+		pArgs = PyTuple_New(2);
+		PyTuple_SetItem(pArgs, 0, PyLong_FromUnsignedLongLong((uint64_t)cpu));
+		PyTuple_SetItem(pArgs, 1, PyLong_FromUnsignedLongLong((uint64_t)vm));
+		ret = PyObject_CallObject(func, pArgs);
+		Py_DECREF(2);
+
+		if (ret == Py_None) {
+			Py_INCREF(Py_None);
+			return Py_None;
+		}
+		func = ret;
+	}
+
+	return ret;
+}
+
+
+
+static PyObject *TccError;
+
+
+static PyMethodDef TccMethods[] = {
+    {"tcc_set_emul_lib_path",  tcc_set_emul_lib_path, METH_VARARGS,
+     "init tcc path"},
+    {"tcc_exec_bloc",  tcc_exec_bloc, METH_VARARGS,
+     "tcc exec bloc"},
+    {"tcc_compil",  tcc_compil, METH_VARARGS,
+     "tcc compil"},
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+
+PyMODINIT_FUNC
+initJittcc(void)
+{
+    PyObject *m;
+
+    m = Py_InitModule("Jittcc", TccMethods);
+    if (m == NULL)
+	    return;
+
+    TccError = PyErr_NewException("tcc.error", NULL, NULL);
+    Py_INCREF(TccError);
+    PyModule_AddObject(m, "error", TccError);
+}
+
diff --git a/miasm2/jitter/Makefile b/miasm2/jitter/Makefile
new file mode 100644
index 00000000..7d43f28c
--- /dev/null
+++ b/miasm2/jitter/Makefile
@@ -0,0 +1,17 @@
+all: vm_mngr.so Jit_x86.so Jittcc.so
+	
+
+vm_mngr.so: vm_mngr.c vm_mngr.h vm_mngr_py.c
+	gcc -I /usr/include/python2.7  -shared -fPIC vm_mngr.c vm_mngr_py.c -o vm_mngr.so
+
+Jit_x86.so: arch/Jit_x86.c
+	gcc -I /usr/include/python2.7  -shared -fPIC arch/Jit_x86.c -o arch/Jit_x86.so
+
+Jit_arm.so: arch/Jit_arm.c
+	gcc -I /usr/include/python2.7  -shared -fPIC arch/Jit_arm.c -o arch/Jit_arm.so
+
+Jittcc.so: Jittcc.c
+	gcc -I /usr/include/python2.7  -shared -fPIC Jittcc.c -o Jittcc.so -ltcc
+
+clean:
+	rm vm_mngr.so Jittcc.so arch/Jit_x86.so
\ No newline at end of file
diff --git a/miasm2/jitter/__init__.py b/miasm2/jitter/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/miasm2/jitter/__init__.py
diff --git a/miasm2/jitter/arch/JitCore.h b/miasm2/jitter/arch/JitCore.h
new file mode 100644
index 00000000..2686cb46
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore.h
@@ -0,0 +1,66 @@
+
+#define PyGetInt(item, value)						\
+	if (PyInt_Check(item)){						\
+		value = (uint64_t)PyInt_AsLong(item);			\
+	}								\
+	else if (PyLong_Check(item)){					\
+		value = (uint64_t)PyLong_AsUnsignedLongLong(item);	\
+	}								\
+	else{								\
+		RAISE(PyExc_TypeError,"arg must be int");		\
+	}								\
+
+
+#define PyGetInt_ret0(item, value)					\
+	if (PyInt_Check(item)){						\
+		value = (uint64_t)PyInt_AsLong(item);			\
+	}								\
+	else if (PyLong_Check(item)){					\
+		value = (uint64_t)PyLong_AsUnsignedLongLong(item);	\
+	}								\
+	else{								\
+		printf("error\n"); return 0;				\
+	}								\
+
+
+
+#define getset_reg_u64(regname)						\
+	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
+	{								\
+		return PyLong_FromUnsignedLongLong((uint64_t)(self->vmcpu.  regname  )); \
+	}								\
+	static int JitCpu_set_ ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint64_t val;						\
+		PyGetInt_ret0(value, val);				\
+		self->vmcpu.  regname   = val;				\
+		return 0;						\
+	}
+
+#define getset_reg_u32(regname)						\
+	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
+	{								\
+		return PyLong_FromUnsignedLongLong((uint32_t)(self->vmcpu.  regname  )); \
+	}								\
+	static int JitCpu_set_ ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint32_t val;						\
+		PyGetInt_ret0(value, val);				\
+		self->vmcpu.  regname   = val;				\
+		return 0;						\
+	}
+
+
+#define getset_reg_u16(regname)						\
+	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
+	{								\
+		return PyLong_FromUnsignedLongLong((uint16_t)(self->vmcpu.  regname  )); \
+	}								\
+	static int JitCpu_set_ ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint16_t val;						\
+		PyGetInt_ret0(value, val);				\
+		self->vmcpu.  regname   = val;				\
+		return 0;						\
+	}
+
diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c
new file mode 100644
index 00000000..7e64ae77
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_arm.c
@@ -0,0 +1,388 @@
+#include <Python.h>
+#include "JitCore.h"
+#include "structmember.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "JitCore_arm.h"
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+typedef struct _reg_dict{
+    char* name;
+    unsigned long offset;
+} reg_dict;
+
+
+#define PyGetInt(item, value)						\
+	if (PyInt_Check(item)){						\
+		value = (uint64_t)PyInt_AsLong(item);			\
+	}								\
+	else if (PyLong_Check(item)){					\
+		value = (uint64_t)PyLong_AsUnsignedLongLong(item);	\
+	}								\
+	else{								\
+		RAISE(PyExc_TypeError,"arg must be int");		\
+	}								\
+
+reg_dict gpreg_dict[] = { {.name = "R0", .offset = offsetof(vm_cpu_t, R0)},
+			  {.name = "R1", .offset = offsetof(vm_cpu_t, R1)},
+			  {.name = "R2", .offset = offsetof(vm_cpu_t, R2)},
+			  {.name = "R3", .offset = offsetof(vm_cpu_t, R3)},
+			  {.name = "R4", .offset = offsetof(vm_cpu_t, R4)},
+			  {.name = "R5", .offset = offsetof(vm_cpu_t, R5)},
+			  {.name = "R6", .offset = offsetof(vm_cpu_t, R6)},
+			  {.name = "R7", .offset = offsetof(vm_cpu_t, R7)},
+			  {.name = "R8", .offset = offsetof(vm_cpu_t, R8)},
+			  {.name = "R9", .offset = offsetof(vm_cpu_t, R9)},
+			  {.name = "R10", .offset = offsetof(vm_cpu_t, R10)},
+			  {.name = "R11", .offset = offsetof(vm_cpu_t, R11)},
+			  {.name = "R12", .offset = offsetof(vm_cpu_t, R12)},
+			  {.name = "SP", .offset = offsetof(vm_cpu_t, SP)},
+			  {.name = "LR", .offset = offsetof(vm_cpu_t, LR)},
+			  {.name = "PC", .offset = offsetof(vm_cpu_t, PC)},
+
+			  {.name = "zf", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "nf", .offset = offsetof(vm_cpu_t, nf)},
+			  {.name = "of", .offset = offsetof(vm_cpu_t, of)},
+			  {.name = "cf", .offset = offsetof(vm_cpu_t, cf)},
+};
+
+/************************** JitCpu object **************************/
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *cpu; /* cpu */
+	vm_cpu_t vmcpu;
+} JitCpu;
+
+
+
+#define get_reg(reg)  do {						\
+		o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \
+		PyDict_SetItemString(dict, #reg, o);			\
+		Py_DECREF(o);						\
+	} while(0);
+
+
+
+PyObject* vm_get_gpreg(JitCpu* self)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+    get_reg(R0);
+    get_reg(R1);
+    get_reg(R2);
+    get_reg(R3);
+    get_reg(R4);
+    get_reg(R5);
+    get_reg(R6);
+    get_reg(R7);
+    get_reg(R8);
+    get_reg(R9);
+    get_reg(R10);
+    get_reg(R11);
+    get_reg(R12);
+    get_reg(SP);
+    get_reg(LR);
+    get_reg(PC);
+
+    get_reg(zf);
+    get_reg(nf);
+    get_reg(of);
+    get_reg(cf);
+
+    return dict;
+}
+
+PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict)
+{
+    PyObject *d_key, *d_value = NULL;
+    Py_ssize_t pos = 0;
+    uint64_t val;
+    unsigned int i, found;
+
+    if(!PyDict_Check(dict))
+	    RAISE(PyExc_TypeError, "arg must be dict");
+    while(PyDict_Next(dict, &pos, &d_key, &d_value)){
+	    if(!PyString_Check(d_key))
+		    RAISE(PyExc_TypeError, "key must be str");
+
+	    PyGetInt(d_value, val);
+
+
+	    found = 0;
+	    for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){
+		    if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name))
+			    continue;
+		    *((uint32_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val;
+		    found = 1;
+		    break;
+	    }
+
+	    if (found)
+		    continue;
+	    fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key));
+	    RAISE(PyExc_ValueError, "unkown reg");
+    }
+    return NULL;
+}
+
+PyObject* vm_set_gpreg(JitCpu* self, PyObject *args)
+{
+	PyObject* dict;
+	if (!PyArg_ParseTuple(args, "O", &dict))
+		return NULL;
+	_vm_set_gpreg(self, dict);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_set_exception(JitCpu* self, PyObject* args)
+{
+	PyObject *item1;
+	uint64_t i;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		return NULL;
+
+	PyGetInt(item1, i);
+
+	self->vmcpu.exception_flags = i;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_exception(JitCpu* self, PyObject* args)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags);
+}
+
+
+PyObject * vm_init_regs(JitCpu* self)
+{
+	memset(&self->vmcpu, 0, sizeof(vm_cpu_t));
+
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+void dump_gpregs(vm_cpu_t* vmcpu)
+{
+	printf("R0 %.16"PRIX32" R1 %.16"PRIX32" R2 %.16"PRIX32" R3 %.16"PRIX32"\n",
+	       vmcpu->R0, vmcpu->R1, vmcpu->R2, vmcpu->R3);
+	printf("R4 %.16"PRIX32" R5 %.16"PRIX32" R6 %.16"PRIX32" R7 %.16"PRIX32"\n",
+	       vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7);
+	printf("R8 %.16"PRIX32" R9 %.16"PRIX32" R10 %.16"PRIX32" R11 %.16"PRIX32"\n",
+	       vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11);
+	printf("R12 %.16"PRIX32" SP %.16"PRIX32" LR %.16"PRIX32" PC %.16"PRIX32"\n",
+	       vmcpu->R12, vmcpu->SP, vmcpu->LR, vmcpu->PC);
+	printf("zf %.16"PRIX32" nf %.16"PRIX32" of %.16"PRIX32" cf %.16"PRIX32"\n",
+	       vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf);
+}
+
+
+PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args)
+{
+	vm_cpu_t* vmcpu;
+
+	vmcpu = &self->vmcpu;
+	dump_gpregs(vmcpu);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+
+static void
+JitCpu_dealloc(JitCpu* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject *
+JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    JitCpu *self;
+
+    self = (JitCpu *)type->tp_alloc(type, 0);
+    return (PyObject *)self;
+}
+
+static PyObject *
+JitCpu_get_cpu(JitCpu *self, void *closure)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu));
+}
+
+static int
+JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure)
+{
+	PyErr_SetString(PyExc_TypeError, "immutable cpu");
+	return -1;
+}
+
+static PyMemberDef JitCpu_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef JitCpu_methods[] = {
+	{"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS,
+	 "X"},
+	{"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS,
+	 "X"},
+	{"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS,
+	 "X"},
+	{"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS,
+	 "X"},
+	{"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS,
+	 "X"},
+	{"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS,
+	 "X"},
+	{NULL}  /* Sentinel */
+};
+
+static int
+JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds)
+{
+
+
+	fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu));
+
+	return 0;
+}
+
+getset_reg_u32(R0);
+getset_reg_u32(R1);
+getset_reg_u32(R2);
+getset_reg_u32(R3);
+getset_reg_u32(R4);
+getset_reg_u32(R5);
+getset_reg_u32(R6);
+getset_reg_u32(R7);
+getset_reg_u32(R8);
+getset_reg_u32(R9);
+getset_reg_u32(R10);
+getset_reg_u32(R11);
+getset_reg_u32(R12);
+getset_reg_u32(SP);
+getset_reg_u32(LR);
+getset_reg_u32(PC);
+
+getset_reg_u32(zf);
+getset_reg_u32(nf);
+getset_reg_u32(of);
+getset_reg_u32(cf);
+
+
+static PyGetSetDef JitCpu_getseters[] = {
+    {"cpu",
+     (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu,
+     "first name",
+     NULL},
+
+    {"R0" , (getter)JitCpu_get_R0 , (setter)JitCpu_set_R0 , "R0" , NULL},
+    {"R1" , (getter)JitCpu_get_R1 , (setter)JitCpu_set_R1 , "R1" , NULL},
+    {"R2" , (getter)JitCpu_get_R2 , (setter)JitCpu_set_R2 , "R2" , NULL},
+    {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL},
+    {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL},
+    {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL},
+    {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL},
+    {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL},
+    {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL},
+    {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL},
+    {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL},
+    {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL},
+    {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL},
+    {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL},
+    {"LR" , (getter)JitCpu_get_LR , (setter)JitCpu_set_LR , "LR" , NULL},
+    {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL},
+
+    {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL},
+    {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL},
+    {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL},
+    {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL},
+
+    {NULL}  /* Sentinel */
+};
+
+
+static PyTypeObject JitCpuType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "JitCore_arm.JitCpu",      /*tp_name*/
+    sizeof(JitCpu),            /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)JitCpu_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "JitCpu objects",          /* tp_doc */
+    0,			       /* tp_traverse */
+    0,			       /* tp_clear */
+    0,			       /* tp_richcompare */
+    0,			       /* tp_weaklistoffset */
+    0,			       /* tp_iter */
+    0,			       /* tp_iternext */
+    JitCpu_methods,            /* tp_methods */
+    JitCpu_members,            /* tp_members */
+    JitCpu_getseters,          /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)JitCpu_init,     /* tp_init */
+    0,                         /* tp_alloc */
+    JitCpu_new,                /* tp_new */
+};
+
+
+
+static PyMethodDef JitCore_arm_Methods[] = {
+
+	/*
+
+	*/
+	{NULL, NULL, 0, NULL}        /* Sentinel */
+
+};
+
+static PyObject *JitCore_arm_Error;
+
+PyMODINIT_FUNC
+initJitCore_arm(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&JitCpuType) < 0)
+	return;
+
+    m = Py_InitModule("JitCore_arm", JitCore_arm_Methods);
+    if (m == NULL)
+	    return;
+
+    JitCore_arm_Error = PyErr_NewException("JitCore_arm.error", NULL, NULL);
+    Py_INCREF(JitCore_arm_Error);
+    PyModule_AddObject(m, "error", JitCore_arm_Error);
+
+    Py_INCREF(&JitCpuType);
+    PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType);
+
+}
+
diff --git a/miasm2/jitter/arch/JitCore_arm.h b/miasm2/jitter/arch/JitCore_arm.h
new file mode 100644
index 00000000..e92db860
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_arm.h
@@ -0,0 +1,147 @@
+
+typedef struct {
+	uint32_t exception_flags;
+	uint32_t exception_flags_new;
+
+	/* gpregs */
+	uint32_t R0;
+	uint32_t R1;
+	uint32_t R2;
+	uint32_t R3;
+	uint32_t R4;
+	uint32_t R5;
+	uint32_t R6;
+	uint32_t R7;
+	uint32_t R8;
+	uint32_t R9;
+	uint32_t R10;
+	uint32_t R11;
+	uint32_t R12;
+	uint32_t SP;
+	uint32_t LR;
+	uint32_t PC;
+
+	uint32_t R0_new;
+	uint32_t R1_new;
+	uint32_t R2_new;
+	uint32_t R3_new;
+	uint32_t R4_new;
+	uint32_t R5_new;
+	uint32_t R6_new;
+	uint32_t R7_new;
+	uint32_t R8_new;
+	uint32_t R9_new;
+	uint32_t R10_new;
+	uint32_t R11_new;
+	uint32_t R12_new;
+	uint32_t SP_new;
+	uint32_t LR_new;
+	uint32_t PC_new;
+
+	/* eflag */
+	uint32_t zf;
+	uint32_t nf;
+	uint32_t of;
+	uint32_t cf;
+
+	uint32_t zf_new;
+	uint32_t nf_new;
+	uint32_t of_new;
+	uint32_t cf_new;
+
+
+	uint8_t pfmem08_0;
+	uint8_t pfmem08_1;
+	uint8_t pfmem08_2;
+	uint8_t pfmem08_3;
+	uint8_t pfmem08_4;
+	uint8_t pfmem08_5;
+	uint8_t pfmem08_6;
+	uint8_t pfmem08_7;
+	uint8_t pfmem08_8;
+	uint8_t pfmem08_9;
+	uint8_t pfmem08_10;
+	uint8_t pfmem08_11;
+	uint8_t pfmem08_12;
+	uint8_t pfmem08_13;
+	uint8_t pfmem08_14;
+	uint8_t pfmem08_15;
+	uint8_t pfmem08_16;
+	uint8_t pfmem08_17;
+	uint8_t pfmem08_18;
+	uint8_t pfmem08_19;
+
+
+	uint16_t pfmem16_0;
+	uint16_t pfmem16_1;
+	uint16_t pfmem16_2;
+	uint16_t pfmem16_3;
+	uint16_t pfmem16_4;
+	uint16_t pfmem16_5;
+	uint16_t pfmem16_6;
+	uint16_t pfmem16_7;
+	uint16_t pfmem16_8;
+	uint16_t pfmem16_9;
+	uint16_t pfmem16_10;
+	uint16_t pfmem16_11;
+	uint16_t pfmem16_12;
+	uint16_t pfmem16_13;
+	uint16_t pfmem16_14;
+	uint16_t pfmem16_15;
+	uint16_t pfmem16_16;
+	uint16_t pfmem16_17;
+	uint16_t pfmem16_18;
+	uint16_t pfmem16_19;
+
+
+	uint32_t pfmem32_0;
+	uint32_t pfmem32_1;
+	uint32_t pfmem32_2;
+	uint32_t pfmem32_3;
+	uint32_t pfmem32_4;
+	uint32_t pfmem32_5;
+	uint32_t pfmem32_6;
+	uint32_t pfmem32_7;
+	uint32_t pfmem32_8;
+	uint32_t pfmem32_9;
+	uint32_t pfmem32_10;
+	uint32_t pfmem32_11;
+	uint32_t pfmem32_12;
+	uint32_t pfmem32_13;
+	uint32_t pfmem32_14;
+	uint32_t pfmem32_15;
+	uint32_t pfmem32_16;
+	uint32_t pfmem32_17;
+	uint32_t pfmem32_18;
+	uint32_t pfmem32_19;
+
+
+	uint64_t pfmem64_0;
+	uint64_t pfmem64_1;
+	uint64_t pfmem64_2;
+	uint64_t pfmem64_3;
+	uint64_t pfmem64_4;
+	uint64_t pfmem64_5;
+	uint64_t pfmem64_6;
+	uint64_t pfmem64_7;
+	uint64_t pfmem64_8;
+	uint64_t pfmem64_9;
+	uint64_t pfmem64_10;
+	uint64_t pfmem64_11;
+	uint64_t pfmem64_12;
+	uint64_t pfmem64_13;
+	uint64_t pfmem64_14;
+	uint64_t pfmem64_15;
+	uint64_t pfmem64_16;
+	uint64_t pfmem64_17;
+	uint64_t pfmem64_18;
+	uint64_t pfmem64_19;
+
+
+	uint32_t segm_base[0x10000];
+
+}vm_cpu_t;
+
+
+
+#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->PC);
diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c
new file mode 100644
index 00000000..17c1497e
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_msp430.c
@@ -0,0 +1,694 @@
+#include <Python.h>
+#include "JitCore.h"
+#include "structmember.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "JitCore_msp430.h"
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+/*
+void check_align(uint64_t addr)
+{
+	if (addr & 1) {
+		printf("unaligned mem lookup %X\n", addr);
+		exit(0);
+	}
+}
+
+void VM_MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src)
+{
+	//check_align(addr);
+	MEM_WRITE_08(vm_mngr, addr, src);
+}
+
+void VM_MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src)
+{
+	check_align(addr);
+	MEM_WRITE_16(vm_mngr, addr, src);
+}
+
+void VM_MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src)
+{
+	check_align(addr);
+	MEM_WRITE_32(vm_mngr, addr, src);
+}
+
+void VM_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src)
+{
+	check_align(addr);
+	MEM_WRITE_64(vm_mngr, addr, src);
+}
+*/
+
+typedef struct _reg_dict{
+    char* name;
+    unsigned long offset;
+} reg_dict;
+
+
+#define PyGetInt(item, value)						\
+	if (PyInt_Check(item)){						\
+		value = (uint64_t)PyInt_AsLong(item);			\
+	}								\
+	else if (PyLong_Check(item)){					\
+		value = (uint64_t)PyLong_AsUnsignedLongLong(item);	\
+	}								\
+	else{								\
+		RAISE(PyExc_TypeError,"arg must be int");		\
+	}								\
+
+reg_dict gpreg_dict[] = { {.name = "PC", .offset = offsetof(vm_cpu_t, PC)},
+			  {.name = "SP", .offset = offsetof(vm_cpu_t, SP)},
+			  //{.name = "SR", .offset = offsetof(vm_cpu_t, SR)},
+			  {.name = "R3", .offset = offsetof(vm_cpu_t, R3)},
+			  {.name = "R4", .offset = offsetof(vm_cpu_t, R4)},
+			  {.name = "R5", .offset = offsetof(vm_cpu_t, R5)},
+			  {.name = "R6", .offset = offsetof(vm_cpu_t, R6)},
+			  {.name = "R7", .offset = offsetof(vm_cpu_t, R7)},
+			  {.name = "R8", .offset = offsetof(vm_cpu_t, R8)},
+			  {.name = "R9", .offset = offsetof(vm_cpu_t, R9)},
+			  {.name = "R10", .offset = offsetof(vm_cpu_t, R10)},
+			  {.name = "R11", .offset = offsetof(vm_cpu_t, R11)},
+			  {.name = "R12", .offset = offsetof(vm_cpu_t, R12)},
+			  {.name = "R13", .offset = offsetof(vm_cpu_t, R13)},
+			  {.name = "R14", .offset = offsetof(vm_cpu_t, R14)},
+			  {.name = "R15", .offset = offsetof(vm_cpu_t, R15)},
+
+			  {.name = "zf", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "nf", .offset = offsetof(vm_cpu_t, nf)},
+			  {.name = "of", .offset = offsetof(vm_cpu_t, of)},
+			  {.name = "cf", .offset = offsetof(vm_cpu_t, cf)},
+
+			  {.name = "cpuoff", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "gie", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "osc", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "scg0", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "scg1", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "res", .offset = offsetof(vm_cpu_t, zf)},
+
+};
+
+/************************** JitCpu object **************************/
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *cpu; /* cpu */
+	vm_cpu_t vmcpu;
+} JitCpu;
+
+
+
+#define get_reg(reg)  do {						\
+		o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \
+		PyDict_SetItemString(dict, #reg, o);			\
+		Py_DECREF(o);						\
+	} while(0);
+
+
+
+PyObject* vm_get_gpreg(JitCpu* self)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+    get_reg(PC);
+    get_reg(SP);
+    //get_reg(SR);
+    get_reg(R3);
+    get_reg(R4);
+    get_reg(R5);
+    get_reg(R6);
+    get_reg(R7);
+    get_reg(R8);
+    get_reg(R9);
+    get_reg(R10);
+    get_reg(R11);
+    get_reg(R12);
+    get_reg(R13);
+    get_reg(R14);
+    get_reg(R15);
+
+    get_reg(zf);
+    get_reg(nf);
+    get_reg(of);
+    get_reg(cf);
+
+    get_reg(cpuoff);
+    get_reg(gie);
+    get_reg(osc);
+    get_reg(scg0);
+    get_reg(scg1);
+    get_reg(res);
+
+
+    return dict;
+}
+
+#define get_reg_off(reg)  do {						\
+		o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(vm_cpu_t, reg)); \
+		PyDict_SetItemString(dict, #reg, o);			\
+		Py_DECREF(o);						\
+	} while(0);
+
+
+PyObject* get_gpreg_offset_all(void)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+    get_reg_off(exception_flags);
+    get_reg_off(exception_flags_new);
+    get_reg_off(PC);
+    get_reg_off(SP);
+    get_reg_off(R3);
+    get_reg_off(R4);
+    get_reg_off(R5);
+    get_reg_off(R6);
+    get_reg_off(R7);
+    get_reg_off(R8);
+    get_reg_off(R9);
+    get_reg_off(R10);
+    get_reg_off(R11);
+    get_reg_off(R12);
+    get_reg_off(R13);
+    get_reg_off(R14);
+    get_reg_off(R15);
+    get_reg_off(PC_new);
+    get_reg_off(SP_new);
+    get_reg_off(SR_new);
+    get_reg_off(R3_new);
+    get_reg_off(R4_new);
+    get_reg_off(R5_new);
+    get_reg_off(R6_new);
+    get_reg_off(R7_new);
+    get_reg_off(R8_new);
+    get_reg_off(R9_new);
+    get_reg_off(R10_new);
+    get_reg_off(R11_new);
+    get_reg_off(R12_new);
+    get_reg_off(R13_new);
+    get_reg_off(R14_new);
+    get_reg_off(R15_new);
+    get_reg_off(zf);
+    get_reg_off(nf);
+    get_reg_off(of);
+    get_reg_off(cf);
+    get_reg_off(cpuoff);
+    get_reg_off(gie);
+    get_reg_off(osc);
+    get_reg_off(scg0);
+    get_reg_off(scg1);
+    get_reg_off(res);
+    get_reg_off(zf_new);
+    get_reg_off(nf_new);
+    get_reg_off(of_new);
+    get_reg_off(cf_new);
+    get_reg_off(cpuoff_new);
+    get_reg_off(gie_new);
+    get_reg_off(osc_new);
+    get_reg_off(scg0_new);
+    get_reg_off(scg1_new);
+    get_reg_off(res_new);
+    get_reg_off(pfmem08_0);
+    get_reg_off(pfmem08_1);
+    get_reg_off(pfmem08_2);
+    get_reg_off(pfmem08_3);
+    get_reg_off(pfmem08_4);
+    get_reg_off(pfmem08_5);
+    get_reg_off(pfmem08_6);
+    get_reg_off(pfmem08_7);
+    get_reg_off(pfmem08_8);
+    get_reg_off(pfmem08_9);
+    get_reg_off(pfmem08_10);
+    get_reg_off(pfmem08_11);
+    get_reg_off(pfmem08_12);
+    get_reg_off(pfmem08_13);
+    get_reg_off(pfmem08_14);
+    get_reg_off(pfmem08_15);
+    get_reg_off(pfmem08_16);
+    get_reg_off(pfmem08_17);
+    get_reg_off(pfmem08_18);
+    get_reg_off(pfmem08_19);
+    get_reg_off(pfmem16_0);
+    get_reg_off(pfmem16_1);
+    get_reg_off(pfmem16_2);
+    get_reg_off(pfmem16_3);
+    get_reg_off(pfmem16_4);
+    get_reg_off(pfmem16_5);
+    get_reg_off(pfmem16_6);
+    get_reg_off(pfmem16_7);
+    get_reg_off(pfmem16_8);
+    get_reg_off(pfmem16_9);
+    get_reg_off(pfmem16_10);
+    get_reg_off(pfmem16_11);
+    get_reg_off(pfmem16_12);
+    get_reg_off(pfmem16_13);
+    get_reg_off(pfmem16_14);
+    get_reg_off(pfmem16_15);
+    get_reg_off(pfmem16_16);
+    get_reg_off(pfmem16_17);
+    get_reg_off(pfmem16_18);
+    get_reg_off(pfmem16_19);
+    get_reg_off(pfmem32_0);
+    get_reg_off(pfmem32_1);
+    get_reg_off(pfmem32_2);
+    get_reg_off(pfmem32_3);
+    get_reg_off(pfmem32_4);
+    get_reg_off(pfmem32_5);
+    get_reg_off(pfmem32_6);
+    get_reg_off(pfmem32_7);
+    get_reg_off(pfmem32_8);
+    get_reg_off(pfmem32_9);
+    get_reg_off(pfmem32_10);
+    get_reg_off(pfmem32_11);
+    get_reg_off(pfmem32_12);
+    get_reg_off(pfmem32_13);
+    get_reg_off(pfmem32_14);
+    get_reg_off(pfmem32_15);
+    get_reg_off(pfmem32_16);
+    get_reg_off(pfmem32_17);
+    get_reg_off(pfmem32_18);
+    get_reg_off(pfmem32_19);
+    get_reg_off(pfmem64_0);
+    get_reg_off(pfmem64_1);
+    get_reg_off(pfmem64_2);
+    get_reg_off(pfmem64_3);
+    get_reg_off(pfmem64_4);
+    get_reg_off(pfmem64_5);
+    get_reg_off(pfmem64_6);
+    get_reg_off(pfmem64_7);
+    get_reg_off(pfmem64_8);
+    get_reg_off(pfmem64_9);
+    get_reg_off(pfmem64_10);
+    get_reg_off(pfmem64_11);
+    get_reg_off(pfmem64_12);
+    get_reg_off(pfmem64_13);
+    get_reg_off(pfmem64_14);
+    get_reg_off(pfmem64_15);
+    get_reg_off(pfmem64_16);
+    get_reg_off(pfmem64_17);
+    get_reg_off(pfmem64_18);
+    get_reg_off(pfmem64_19);
+    return dict;
+}
+
+
+PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict)
+{
+    PyObject *d_key, *d_value = NULL;
+    Py_ssize_t pos = 0;
+    uint64_t val;
+    unsigned int i, found;
+
+    if(!PyDict_Check(dict))
+	    RAISE(PyExc_TypeError, "arg must be dict");
+    while(PyDict_Next(dict, &pos, &d_key, &d_value)){
+	    if(!PyString_Check(d_key))
+		    RAISE(PyExc_TypeError, "key must be str");
+
+	    PyGetInt(d_value, val);
+
+
+	    found = 0;
+	    for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){
+		    if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name))
+			    continue;
+		    *((uint32_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val;
+		    found = 1;
+		    break;
+	    }
+
+	    if (found)
+		    continue;
+	    fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key));
+	    RAISE(PyExc_ValueError, "unkown reg");
+    }
+    return NULL;
+}
+
+uint8_t const bcd2bin_data[] = {
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 0, 0, 0, 0, 0, 0,
+	10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0,
+	20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0,
+	30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0,
+	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, 0, 0,
+	60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0,
+	70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
+	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0,
+	90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+};
+
+uint8_t const bin2bcd_data[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
+};
+
+inline uint16_t bcdadd_16(uint16_t a, uint16_t b)
+{
+	int carry = 0;
+	int i,j = 0;
+	uint16_t res = 0;
+	int nib_a, nib_b;
+	for (i = 0; i < 16; i += 4) {
+		nib_a = (a  >> i) & (0xF);
+		nib_b = (b >> i) & (0xF);
+
+		j = (carry + nib_a + nib_b);
+		if (j >= 10) {
+			carry = 1;
+			j -= 10;
+			j &=0xf;
+		}
+		else {
+			carry = 0;
+		}
+		res += j << i;
+	}
+	return res;
+}
+
+inline uint16_t bcdadd_cf_16(uint16_t a, uint16_t b)
+{
+	int carry = 0;
+	int i,j = 0;
+	int nib_a, nib_b;
+	for (i = 0; i < 16; i += 4) {
+		nib_a = (a >> i) & (0xF);
+		nib_b = (b >> i) & (0xF);
+
+		j = (carry + nib_a + nib_b);
+		if (j >= 10) {
+			carry = 1;
+			j -= 10;
+			j &=0xf;
+		}
+		else {
+			carry = 0;
+		}
+	}
+	return carry;
+}
+
+
+inline uint16_t hex2bcd_16(uint16_t a)
+{
+	return bcd2bin_data[a & 0xFF] + (bcd2bin_data[(a >> 8) & 0xFF] * 100);
+}
+
+inline uint8_t hex2bcd_8(uint8_t a)
+{
+	return bcd2bin_data[a & 0xFF];
+}
+
+inline uint8_t bcd2hex_8(uint8_t a)
+{
+	return bin2bcd_data[a & 0xFF];
+}
+
+inline uint16_t bcd2hex_16(uint16_t a)
+{
+	return bcd2bin_data[a % 100] | (bcd2bin_data[(a / 100)] << 8);
+}
+
+
+PyObject* vm_set_gpreg(JitCpu* self, PyObject *args)
+{
+	PyObject* dict;
+	if (!PyArg_ParseTuple(args, "O", &dict))
+		return NULL;
+	_vm_set_gpreg(self, dict);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_set_exception(JitCpu* self, PyObject* args)
+{
+	PyObject *item1;
+	uint64_t i;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		return NULL;
+
+	PyGetInt(item1, i);
+
+	self->vmcpu.exception_flags = i;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_exception(JitCpu* self, PyObject* args)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags);
+}
+
+
+PyObject * vm_init_regs(JitCpu* self)
+{
+	memset(&self->vmcpu, 0, sizeof(vm_cpu_t));
+
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+void dump_gpregs(vm_cpu_t* vmcpu)
+{
+
+	printf("PC  %.4"PRIX32" SP  %.4"PRIX32"  R3  %.4"PRIX32" ",
+	       vmcpu->PC, vmcpu->SP, vmcpu->R3);
+	printf("R4  %.4"PRIX32" R5  %.4"PRIX32" R6  %.4"PRIX32" R7  %.4"PRIX32"\n",
+	       vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7);
+	printf("R8  %.4"PRIX32" R9  %.4"PRIX32" R10 %.4"PRIX32" R11 %.4"PRIX32" ",
+	       vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11);
+	printf("R12 %.4"PRIX32" R13 %.4"PRIX32" R14 %.4"PRIX32" R15 %.4"PRIX32"\n",
+	       vmcpu->R12, vmcpu->R13, vmcpu->R14, vmcpu->R15);
+	printf("zf %.4"PRIX32" nf %.4"PRIX32" of %.4"PRIX32" cf %.4"PRIX32"\n",
+	       vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf);
+}
+
+
+PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args)
+{
+	vm_cpu_t* vmcpu;
+
+	vmcpu = &self->vmcpu;
+	dump_gpregs(vmcpu);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+
+static void
+JitCpu_dealloc(JitCpu* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject *
+JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    JitCpu *self;
+
+    self = (JitCpu *)type->tp_alloc(type, 0);
+    return (PyObject *)self;
+}
+
+static PyObject *
+JitCpu_get_cpu(JitCpu *self, void *closure)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu));
+}
+
+static int
+JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure)
+{
+	PyErr_SetString(PyExc_TypeError, "immutable cpu");
+	return -1;
+}
+
+static PyMemberDef JitCpu_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef JitCpu_methods[] = {
+	{"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS,
+	 "X"},
+	{"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS,
+	 "X"},
+	{"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS,
+	 "X"},
+	{"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS,
+	 "X"},
+	{"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS,
+	 "X"},
+	{"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS,
+	 "X"},
+	{NULL}  /* Sentinel */
+};
+
+static int
+JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds)
+{
+
+
+	fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu));
+
+	return 0;
+}
+
+getset_reg_u16(PC);
+getset_reg_u16(SP);
+getset_reg_u16(R3);
+getset_reg_u16(R4);
+getset_reg_u16(R5);
+getset_reg_u16(R6);
+getset_reg_u16(R7);
+getset_reg_u16(R8);
+getset_reg_u16(R9);
+getset_reg_u16(R10);
+getset_reg_u16(R11);
+getset_reg_u16(R12);
+getset_reg_u16(R13);
+getset_reg_u16(R14);
+getset_reg_u16(R15);
+getset_reg_u16(zf);
+getset_reg_u16(nf);
+getset_reg_u16(of);
+getset_reg_u16(cf);
+getset_reg_u16(cpuoff);
+getset_reg_u16(gie);
+getset_reg_u16(osc);
+getset_reg_u16(scg0);
+getset_reg_u16(scg1);
+getset_reg_u16(res);
+
+
+
+
+static PyGetSetDef JitCpu_getseters[] = {
+    {"cpu",
+     (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu,
+     "first name",
+     NULL},
+
+
+    {"PC" , (getter)JitCpu_get_PC      , (setter)JitCpu_set_PC     , "PC" , NULL},
+    {"SP" , (getter)JitCpu_get_SP      , (setter)JitCpu_set_SP     , "SP" , NULL},
+    {"R3" , (getter)JitCpu_get_R3      , (setter)JitCpu_set_R3     , "R3" , NULL},
+    {"R4" , (getter)JitCpu_get_R4      , (setter)JitCpu_set_R4     , "R4" , NULL},
+    {"R5" , (getter)JitCpu_get_R5      , (setter)JitCpu_set_R5     , "R5" , NULL},
+    {"R6" , (getter)JitCpu_get_R6      , (setter)JitCpu_set_R6     , "R6" , NULL},
+    {"R7" , (getter)JitCpu_get_R7      , (setter)JitCpu_set_R7     , "R7" , NULL},
+    {"R8" , (getter)JitCpu_get_R8      , (setter)JitCpu_set_R8     , "R8" , NULL},
+    {"R9" , (getter)JitCpu_get_R9      , (setter)JitCpu_set_R9     , "R9" , NULL},
+    {"R10" , (getter)JitCpu_get_R10    , (setter)JitCpu_set_R10    , "R10" , NULL},
+    {"R11" , (getter)JitCpu_get_R11    , (setter)JitCpu_set_R11    , "R11" , NULL},
+    {"R12" , (getter)JitCpu_get_R12    , (setter)JitCpu_set_R12    , "R12" , NULL},
+    {"R13" , (getter)JitCpu_get_R13    , (setter)JitCpu_set_R13    , "R13" , NULL},
+    {"R14" , (getter)JitCpu_get_R14    , (setter)JitCpu_set_R14    , "R14" , NULL},
+    {"R15" , (getter)JitCpu_get_R15    , (setter)JitCpu_set_R15    , "R15" , NULL},
+    {"zf" , (getter)JitCpu_get_zf      , (setter)JitCpu_set_zf     , "zf" , NULL},
+    {"nf" , (getter)JitCpu_get_nf      , (setter)JitCpu_set_nf     , "nf" , NULL},
+    {"of" , (getter)JitCpu_get_of      , (setter)JitCpu_set_of     , "of" , NULL},
+    {"cf" , (getter)JitCpu_get_cf      , (setter)JitCpu_set_cf     , "cf" , NULL},
+    {"cpuoff" , (getter)JitCpu_get_cpuoff , (setter)JitCpu_set_cpuoff , "cpuoff" , NULL},
+    {"gie" , (getter)JitCpu_get_gie    , (setter)JitCpu_set_gie    , "gie" , NULL},
+    {"osc" , (getter)JitCpu_get_osc    , (setter)JitCpu_set_osc    , "osc" , NULL},
+    {"scg0" , (getter)JitCpu_get_scg0   , (setter)JitCpu_set_scg0   , "scg0" , NULL},
+    {"scg1" , (getter)JitCpu_get_scg1   , (setter)JitCpu_set_scg1   , "scg1" , NULL},
+    {"res" , (getter)JitCpu_get_res    , (setter)JitCpu_set_res    , "res" , NULL},
+
+    {NULL}  /* Sentinel */
+};
+
+
+
+static PyTypeObject JitCpuType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "JitCore_msp430.JitCpu",   /*tp_name*/
+    sizeof(JitCpu),            /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)JitCpu_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "JitCpu objects",          /* tp_doc */
+    0,			       /* tp_traverse */
+    0,			       /* tp_clear */
+    0,			       /* tp_richcompare */
+    0,			       /* tp_weaklistoffset */
+    0,			       /* tp_iter */
+    0,			       /* tp_iternext */
+    JitCpu_methods,            /* tp_methods */
+    JitCpu_members,            /* tp_members */
+    JitCpu_getseters,          /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)JitCpu_init,     /* tp_init */
+    0,                         /* tp_alloc */
+    JitCpu_new,                /* tp_new */
+};
+
+
+
+static PyMethodDef JitCore_msp430_Methods[] = {
+
+	/*
+
+	*/
+	{"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS},
+	{NULL, NULL, 0, NULL}        /* Sentinel */
+
+};
+
+static PyObject *JitCore_msp430_Error;
+
+PyMODINIT_FUNC
+initJitCore_msp430(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&JitCpuType) < 0)
+	return;
+
+    m = Py_InitModule("JitCore_msp430", JitCore_msp430_Methods);
+    if (m == NULL)
+	    return;
+
+    JitCore_msp430_Error = PyErr_NewException("JitCore_msp430.error", NULL, NULL);
+    Py_INCREF(JitCore_msp430_Error);
+    PyModule_AddObject(m, "error", JitCore_msp430_Error);
+
+    Py_INCREF(&JitCpuType);
+    PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType);
+
+}
+
diff --git a/miasm2/jitter/arch/JitCore_msp430.h b/miasm2/jitter/arch/JitCore_msp430.h
new file mode 100644
index 00000000..c65989b0
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_msp430.h
@@ -0,0 +1,171 @@
+
+typedef struct {
+	uint32_t exception_flags;
+	uint32_t exception_flags_new;
+
+	/* gpregs */
+	uint32_t PC;
+	uint32_t SP;
+	uint32_t R3;
+	uint32_t R4;
+	uint32_t R5;
+	uint32_t R6;
+	uint32_t R7;
+	uint32_t R8;
+	uint32_t R9;
+	uint32_t R10;
+	uint32_t R11;
+	uint32_t R12;
+	uint32_t R13;
+	uint32_t R14;
+	uint32_t R15;
+
+	uint32_t PC_new;
+	uint32_t SP_new;
+	uint32_t SR_new;
+	uint32_t R3_new;
+	uint32_t R4_new;
+	uint32_t R5_new;
+	uint32_t R6_new;
+	uint32_t R7_new;
+	uint32_t R8_new;
+	uint32_t R9_new;
+	uint32_t R10_new;
+	uint32_t R11_new;
+	uint32_t R12_new;
+	uint32_t R13_new;
+	uint32_t R14_new;
+	uint32_t R15_new;
+
+	/* eflag */
+	uint32_t zf;
+	uint32_t nf;
+	uint32_t of;
+	uint32_t cf;
+
+	uint32_t cpuoff;
+	uint32_t gie;
+	uint32_t osc;
+	uint32_t scg0;
+	uint32_t scg1;
+	uint32_t res;
+
+
+	uint32_t zf_new;
+	uint32_t nf_new;
+	uint32_t of_new;
+	uint32_t cf_new;
+
+	uint32_t cpuoff_new;
+	uint32_t gie_new;
+	uint32_t osc_new;
+	uint32_t scg0_new;
+	uint32_t scg1_new;
+	uint32_t res_new;
+
+
+	uint8_t pfmem08_0;
+	uint8_t pfmem08_1;
+	uint8_t pfmem08_2;
+	uint8_t pfmem08_3;
+	uint8_t pfmem08_4;
+	uint8_t pfmem08_5;
+	uint8_t pfmem08_6;
+	uint8_t pfmem08_7;
+	uint8_t pfmem08_8;
+	uint8_t pfmem08_9;
+	uint8_t pfmem08_10;
+	uint8_t pfmem08_11;
+	uint8_t pfmem08_12;
+	uint8_t pfmem08_13;
+	uint8_t pfmem08_14;
+	uint8_t pfmem08_15;
+	uint8_t pfmem08_16;
+	uint8_t pfmem08_17;
+	uint8_t pfmem08_18;
+	uint8_t pfmem08_19;
+
+
+	uint16_t pfmem16_0;
+	uint16_t pfmem16_1;
+	uint16_t pfmem16_2;
+	uint16_t pfmem16_3;
+	uint16_t pfmem16_4;
+	uint16_t pfmem16_5;
+	uint16_t pfmem16_6;
+	uint16_t pfmem16_7;
+	uint16_t pfmem16_8;
+	uint16_t pfmem16_9;
+	uint16_t pfmem16_10;
+	uint16_t pfmem16_11;
+	uint16_t pfmem16_12;
+	uint16_t pfmem16_13;
+	uint16_t pfmem16_14;
+	uint16_t pfmem16_15;
+	uint16_t pfmem16_16;
+	uint16_t pfmem16_17;
+	uint16_t pfmem16_18;
+	uint16_t pfmem16_19;
+
+
+	uint32_t pfmem32_0;
+	uint32_t pfmem32_1;
+	uint32_t pfmem32_2;
+	uint32_t pfmem32_3;
+	uint32_t pfmem32_4;
+	uint32_t pfmem32_5;
+	uint32_t pfmem32_6;
+	uint32_t pfmem32_7;
+	uint32_t pfmem32_8;
+	uint32_t pfmem32_9;
+	uint32_t pfmem32_10;
+	uint32_t pfmem32_11;
+	uint32_t pfmem32_12;
+	uint32_t pfmem32_13;
+	uint32_t pfmem32_14;
+	uint32_t pfmem32_15;
+	uint32_t pfmem32_16;
+	uint32_t pfmem32_17;
+	uint32_t pfmem32_18;
+	uint32_t pfmem32_19;
+
+
+	uint64_t pfmem64_0;
+	uint64_t pfmem64_1;
+	uint64_t pfmem64_2;
+	uint64_t pfmem64_3;
+	uint64_t pfmem64_4;
+	uint64_t pfmem64_5;
+	uint64_t pfmem64_6;
+	uint64_t pfmem64_7;
+	uint64_t pfmem64_8;
+	uint64_t pfmem64_9;
+	uint64_t pfmem64_10;
+	uint64_t pfmem64_11;
+	uint64_t pfmem64_12;
+	uint64_t pfmem64_13;
+	uint64_t pfmem64_14;
+	uint64_t pfmem64_15;
+	uint64_t pfmem64_16;
+	uint64_t pfmem64_17;
+	uint64_t pfmem64_18;
+	uint64_t pfmem64_19;
+
+
+	uint32_t segm_base[0x10000];
+
+}vm_cpu_t;
+
+#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->PC);
+
+uint16_t bcdadd_16(uint16_t a, uint16_t b);
+
+uint16_t bcdadd_cf_16(uint16_t a, uint16_t b);
+
+uint16_t hex2bcd_16(uint16_t a);
+
+uint8_t hex2bcd_8(uint8_t a);
+
+uint8_t bcd2hex_8(uint8_t a);
+
+uint16_t bcd2hex_16(uint16_t a);
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
new file mode 100644
index 00000000..107491c1
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -0,0 +1,873 @@
+#include <Python.h>
+#include "JitCore.h"
+#include "structmember.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "../queue.h"
+#include "../vm_mngr.h"
+#include "JitCore_x86.h"
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+#define RAISE_ret0(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return 0;}
+
+typedef struct _reg_dict{
+    char* name;
+    size_t offset;
+} reg_dict;
+
+
+reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX)},
+			  {.name = "RBX", .offset = offsetof(vm_cpu_t, RBX)},
+			  {.name = "RCX", .offset = offsetof(vm_cpu_t, RCX)},
+			  {.name = "RDX", .offset = offsetof(vm_cpu_t, RDX)},
+			  {.name = "RSI", .offset = offsetof(vm_cpu_t, RSI)},
+			  {.name = "RDI", .offset = offsetof(vm_cpu_t, RDI)},
+			  {.name = "RSP", .offset = offsetof(vm_cpu_t, RSP)},
+			  {.name = "RBP", .offset = offsetof(vm_cpu_t, RBP)},
+
+			  {.name = "R8", .offset = offsetof(vm_cpu_t, R8)},
+			  {.name = "R9", .offset = offsetof(vm_cpu_t, R9)},
+			  {.name = "R10", .offset = offsetof(vm_cpu_t, R10)},
+			  {.name = "R11", .offset = offsetof(vm_cpu_t, R11)},
+			  {.name = "R12", .offset = offsetof(vm_cpu_t, R12)},
+			  {.name = "R13", .offset = offsetof(vm_cpu_t, R13)},
+			  {.name = "R14", .offset = offsetof(vm_cpu_t, R14)},
+			  {.name = "R15", .offset = offsetof(vm_cpu_t, R15)},
+
+			  {.name = "RIP", .offset = offsetof(vm_cpu_t, RIP)},
+
+			  {.name = "zf", .offset = offsetof(vm_cpu_t, zf)},
+			  {.name = "nf", .offset = offsetof(vm_cpu_t, nf)},
+			  {.name = "pf", .offset = offsetof(vm_cpu_t, pf)},
+			  {.name = "of", .offset = offsetof(vm_cpu_t, of)},
+			  {.name = "cf", .offset = offsetof(vm_cpu_t, cf)},
+			  {.name = "af", .offset = offsetof(vm_cpu_t, af)},
+			  {.name = "df", .offset = offsetof(vm_cpu_t, df)},
+
+			  {.name = "ES", .offset = offsetof(vm_cpu_t, ES)},
+			  {.name = "CS", .offset = offsetof(vm_cpu_t, CS)},
+			  {.name = "SS", .offset = offsetof(vm_cpu_t, SS)},
+			  {.name = "DS", .offset = offsetof(vm_cpu_t, DS)},
+			  {.name = "FS", .offset = offsetof(vm_cpu_t, FS)},
+			  {.name = "GS", .offset = offsetof(vm_cpu_t, GS)},
+
+};
+
+
+
+/************************** JitCpu object **************************/
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *cpu; /* cpu */
+	vm_cpu_t vmcpu;
+} JitCpu;
+
+
+
+#define get_reg(reg)  do {						\
+		o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \
+		PyDict_SetItemString(dict, #reg, o);			\
+		Py_DECREF(o);						\
+	} while(0);
+
+
+PyObject* vm_get_gpreg(JitCpu* self)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+    get_reg(RAX);
+    get_reg(RBX);
+    get_reg(RCX);
+    get_reg(RDX);
+    get_reg(RSI);
+    get_reg(RDI);
+    get_reg(RSP);
+    get_reg(RBP);
+
+    get_reg(R8);
+    get_reg(R9);
+    get_reg(R10);
+    get_reg(R11);
+    get_reg(R12);
+    get_reg(R13);
+    get_reg(R14);
+    get_reg(R15);
+
+    get_reg(RIP);
+
+    get_reg(zf);
+    get_reg(nf);
+    get_reg(pf);
+    get_reg(of);
+    get_reg(cf);
+    get_reg(af);
+    get_reg(df);
+
+
+    get_reg(ES);
+    get_reg(CS);
+    get_reg(SS);
+    get_reg(DS);
+    get_reg(FS);
+    get_reg(GS);
+
+    return dict;
+}
+
+
+
+
+PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict)
+{
+    PyObject *d_key, *d_value = NULL;
+    Py_ssize_t pos = 0;
+    uint64_t val;
+    unsigned int i, found;
+
+    if(!PyDict_Check(dict))
+	    RAISE(PyExc_TypeError, "arg must be dict");
+    while(PyDict_Next(dict, &pos, &d_key, &d_value)){
+	    if(!PyString_Check(d_key))
+		    RAISE(PyExc_TypeError, "key must be str");
+
+	    PyGetInt(d_value, val);
+
+	    found = 0;
+	    for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){
+		    if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name))
+			    continue;
+		    *((uint64_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val;
+		    found = 1;
+		    break;
+	    }
+
+	    if (found)
+		    continue;
+	    fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key));
+	    RAISE(PyExc_ValueError, "unkown reg");
+    }
+    return NULL;
+}
+
+PyObject* vm_set_gpreg(JitCpu* self, PyObject *args)
+{
+	PyObject* dict;
+	if (!PyArg_ParseTuple(args, "O", &dict))
+		return NULL;
+	_vm_set_gpreg(self, dict);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject * vm_init_regs(JitCpu* self)
+{
+	memset(&self->vmcpu, 0, sizeof(vm_cpu_t));
+
+	self->vmcpu.tsc1 = 0x22222222;
+	self->vmcpu.tsc2 = 0x11111111;
+	self->vmcpu.i_f = 1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+void dump_gpregs(vm_cpu_t* vmcpu)
+{
+
+	printf("RAX %.16"PRIX64" RBX %.16"PRIX64" RCX %.16"PRIX64" RDX %.16"PRIX64"\n",
+	       vmcpu->RAX, vmcpu->RBX, vmcpu->RCX, vmcpu->RDX);
+	printf("RSI %.16"PRIX64" RDI %.16"PRIX64" RSP %.16"PRIX64" RBP %.16"PRIX64"\n",
+	       vmcpu->RSI, vmcpu->RDI, vmcpu->RSP, vmcpu->RBP);
+	printf("zf %.16"PRIX64" nf %.16"PRIX64" of %.16"PRIX64" cf %.16"PRIX64"\n",
+	       vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf);
+	printf("RIP %.16"PRIX64"\n",
+	       vmcpu->RIP);
+
+}
+
+PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args)
+{
+	vm_cpu_t* vmcpu;
+
+	vmcpu = &self->vmcpu;
+	dump_gpregs(vmcpu);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_set_segm_base(JitCpu* self, PyObject* args)
+{
+	PyObject *item1, *item2;
+	uint64_t segm_num, segm_base;
+
+	if (!PyArg_ParseTuple(args, "OO", &item1, &item2))
+		return NULL;
+
+	PyGetInt(item1, segm_num);
+	PyGetInt(item2, segm_base);
+	self->vmcpu.segm_base[segm_num] = segm_base;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_segm_base(JitCpu* self, PyObject* args)
+{
+	PyObject *item1;
+	uint64_t segm_num;
+	PyObject* v;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		return NULL;
+	PyGetInt(item1, segm_num);
+	v = PyInt_FromLong((long)self->vmcpu.segm_base[segm_num]);
+	return v;
+}
+
+uint64_t segm2addr(vm_cpu_t* vmcpu, uint64_t segm, uint64_t addr)
+{
+	return addr + vmcpu->segm_base[segm];
+}
+
+
+PyObject* vm_set_exception(JitCpu* self, PyObject* args)
+{
+	PyObject *item1;
+	uint64_t i;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		return NULL;
+
+	PyGetInt(item1, i);
+
+	self->vmcpu.exception_flags = i;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_exception(JitCpu* self, PyObject* args)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags);
+}
+
+
+
+#define UDIV(sizeA, sizeB)						\
+    uint ## sizeA ## _t udiv ## sizeB (vm_cpu_t* vmcpu, uint ## sizeB ## _t a, uint ## sizeB ## _t b) \
+	    {								\
+	    uint ## sizeA ## _t r;						\
+	    if (b == 0) {						\
+		    vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO;	\
+		    return 0;						\
+	    }								\
+	    r = a/b;							\
+	    return r;							\
+	    }
+
+
+#define UMOD(sizeA, sizeB)						\
+    uint ## sizeA ## _t umod ## sizeB (vm_cpu_t* vmcpu, uint ## sizeB ## _t a, uint ## sizeB ## _t b) \
+	    {								\
+	    uint ## sizeA ## _t r;						\
+	    if (b == 0) {						\
+		    vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO;	\
+		    return 0;						\
+	    }								\
+	    r = a%b;							\
+	    return r;							\
+	    }
+
+
+#define IDIV(sizeA)						\
+    int ## sizeA ## _t idiv ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \
+	    {								\
+	    int ## sizeA ## _t r;						\
+	    if (b == 0) {						\
+		    vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO;	\
+		    return 0;						\
+	    }								\
+	    r = a/b;							\
+	    return r;							\
+	    }
+
+
+#define IMOD(sizeA)						\
+    int ## sizeA ## _t imod ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \
+	    {								\
+	    int ## sizeA ## _t r;						\
+	    if (b == 0) {						\
+		    vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO;	\
+		    return 0;						\
+	    }								\
+	    r = a%b;							\
+	    return r;							\
+	    }
+
+UDIV(8, 16)
+UDIV(16, 32)
+UDIV(32, 64)
+
+UMOD(8, 16)
+UMOD(16, 32)
+UMOD(32, 64)
+
+
+IDIV(16)
+IDIV(32)
+IDIV(64)
+
+IMOD(16)
+IMOD(32)
+IMOD(64)
+
+
+
+
+static void
+JitCpu_dealloc(JitCpu* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject *
+JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    JitCpu *self;
+
+    self = (JitCpu *)type->tp_alloc(type, 0);
+    return (PyObject *)self;
+}
+
+static PyObject *
+JitCpu_get_cpu(JitCpu *self, void *closure)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu));
+}
+
+static int
+JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure)
+{
+	PyErr_SetString(PyExc_TypeError, "immutable cpu");
+	return -1;
+}
+
+static PyMemberDef JitCpu_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef JitCpu_methods[] = {
+	{"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS,
+	 "X"},
+	{"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS,
+	 "X"},
+	{"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS,
+	 "X"},
+	{"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS,
+	 "X"},
+	{"vm_get_segm_base", (PyCFunction)vm_get_segm_base, METH_VARARGS,
+	 "X"},
+	{"vm_set_segm_base", (PyCFunction)vm_set_segm_base, METH_VARARGS,
+	 "X"},
+	{"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS,
+	 "X"},
+	{"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS,
+	 "X"},
+	{NULL}  /* Sentinel */
+};
+
+static int
+JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds)
+{
+
+
+	fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu));
+
+	return 0;
+}
+/*
+static PyObject *JitCpu_get_RAX(JitCpu *self, void *closure)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)(self->vmcpu.RAX));
+}
+
+static int JitCpu_set_RAX(JitCpu *self, PyObject *value, void *closure)
+{
+	uint64_t val;
+	PyGetInt_ret0(value, val);
+	self->vmcpu.RAX = val;
+	return 0;
+}
+*/
+
+
+#define getset_reg_E_u32(regname)						\
+	static PyObject *JitCpu_get_E ## regname  (JitCpu *self, void *closure) \
+	{								\
+		return PyLong_FromUnsignedLongLong((uint32_t)(self->vmcpu.R ## regname & 0xFFFFFFFF  )); \
+	}								\
+	static int JitCpu_set_E ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint64_t val;						\
+		PyGetInt_ret0(value, val);				\
+		val &= 0xFFFFFFFF;					\
+		val |= self->vmcpu.R ##regname & 0xFFFFFFFF00000000ULL; \
+		self->vmcpu.R ## regname   = val;			\
+		return 0;						\
+	}
+
+
+
+#define getset_reg_R_u16(regname)						\
+	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
+	{								\
+		return PyLong_FromUnsignedLongLong((uint16_t)(self->vmcpu.R ## regname & 0xFFFF  )); \
+	}								\
+	static int JitCpu_set_ ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint64_t val;						\
+		PyGetInt_ret0(value, val);				\
+		val &= 0xFFFF;						\
+		val |= self->vmcpu.R ##regname & 0xFFFFFFFFFFFF0000ULL; \
+		self->vmcpu.R ## regname   = val;			\
+		return 0;						\
+	}
+
+
+getset_reg_u64(RAX);
+getset_reg_u64(RBX);
+getset_reg_u64(RCX);
+getset_reg_u64(RDX);
+getset_reg_u64(RSI);
+getset_reg_u64(RDI);
+getset_reg_u64(RSP);
+getset_reg_u64(RBP);
+
+getset_reg_u64(R8);
+getset_reg_u64(R9);
+getset_reg_u64(R10);
+getset_reg_u64(R11);
+getset_reg_u64(R12);
+getset_reg_u64(R13);
+getset_reg_u64(R14);
+getset_reg_u64(R15);
+
+getset_reg_u64(RIP);
+
+getset_reg_u64(zf);
+getset_reg_u64(nf);
+getset_reg_u64(pf);
+getset_reg_u64(of);
+getset_reg_u64(cf);
+getset_reg_u64(af);
+getset_reg_u64(df);
+
+
+getset_reg_u64(ES);
+getset_reg_u64(CS);
+getset_reg_u64(SS);
+getset_reg_u64(DS);
+getset_reg_u64(FS);
+getset_reg_u64(GS);
+
+
+getset_reg_E_u32(AX);
+getset_reg_E_u32(BX);
+getset_reg_E_u32(CX);
+getset_reg_E_u32(DX);
+getset_reg_E_u32(SI);
+getset_reg_E_u32(DI);
+getset_reg_E_u32(SP);
+getset_reg_E_u32(BP);
+getset_reg_E_u32(IP);
+
+getset_reg_R_u16(AX);
+getset_reg_R_u16(BX);
+getset_reg_R_u16(CX);
+getset_reg_R_u16(DX);
+getset_reg_R_u16(SI);
+getset_reg_R_u16(DI);
+getset_reg_R_u16(SP);
+getset_reg_R_u16(BP);
+
+#define get_reg_off(reg)  do {						\
+		o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(vm_cpu_t, reg)); \
+		PyDict_SetItemString(dict, #reg, o);			\
+		Py_DECREF(o);						\
+	} while(0);
+
+
+PyObject* get_gpreg_offset_all(void)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+    get_reg_off(exception_flags);
+    get_reg_off(exception_flags_new);
+
+    get_reg_off(RAX);
+    get_reg_off(RBX);
+    get_reg_off(RCX);
+    get_reg_off(RDX);
+    get_reg_off(RSI);
+    get_reg_off(RDI);
+    get_reg_off(RSP);
+    get_reg_off(RBP);
+    get_reg_off(R8);
+    get_reg_off(R9);
+    get_reg_off(R10);
+    get_reg_off(R11);
+    get_reg_off(R12);
+    get_reg_off(R13);
+    get_reg_off(R14);
+    get_reg_off(R15);
+    get_reg_off(RIP);
+    get_reg_off(RAX_new);
+    get_reg_off(RBX_new);
+    get_reg_off(RCX_new);
+    get_reg_off(RDX_new);
+    get_reg_off(RSI_new);
+    get_reg_off(RDI_new);
+    get_reg_off(RSP_new);
+    get_reg_off(RBP_new);
+    get_reg_off(R8_new);
+    get_reg_off(R9_new);
+    get_reg_off(R10_new);
+    get_reg_off(R11_new);
+    get_reg_off(R12_new);
+    get_reg_off(R13_new);
+    get_reg_off(R14_new);
+    get_reg_off(R15_new);
+    get_reg_off(RIP_new);
+    get_reg_off(zf);
+    get_reg_off(nf);
+    get_reg_off(pf);
+    get_reg_off(of);
+    get_reg_off(cf);
+    get_reg_off(af);
+    get_reg_off(df);
+    get_reg_off(zf_new);
+    get_reg_off(nf_new);
+    get_reg_off(pf_new);
+    get_reg_off(of_new);
+    get_reg_off(cf_new);
+    get_reg_off(af_new);
+    get_reg_off(df_new);
+    get_reg_off(tf);
+    get_reg_off(i_f);
+    get_reg_off(iopl_f);
+    get_reg_off(nt);
+    get_reg_off(rf);
+    get_reg_off(vm);
+    get_reg_off(ac);
+    get_reg_off(vif);
+    get_reg_off(vip);
+    get_reg_off(i_d);
+    get_reg_off(tf_new);
+    get_reg_off(i_f_new);
+    get_reg_off(iopl_f_new);
+    get_reg_off(nt_new);
+    get_reg_off(rf_new);
+    get_reg_off(vm_new);
+    get_reg_off(ac_new);
+    get_reg_off(vif_new);
+    get_reg_off(vip_new);
+    get_reg_off(i_d_new);
+    get_reg_off(my_tick);
+    get_reg_off(cond);
+
+    get_reg_off(float_st0);
+    get_reg_off(float_st1);
+    get_reg_off(float_st2);
+    get_reg_off(float_st3);
+    get_reg_off(float_st4);
+    get_reg_off(float_st5);
+    get_reg_off(float_st6);
+    get_reg_off(float_st7);
+    get_reg_off(float_st0_new);
+    get_reg_off(float_st1_new);
+    get_reg_off(float_st2_new);
+    get_reg_off(float_st3_new);
+    get_reg_off(float_st4_new);
+    get_reg_off(float_st5_new);
+    get_reg_off(float_st6_new);
+    get_reg_off(float_st7_new);
+
+    get_reg_off(ES);
+    get_reg_off(CS);
+    get_reg_off(SS);
+    get_reg_off(DS);
+    get_reg_off(FS);
+    get_reg_off(GS);
+    get_reg_off(ES_new);
+    get_reg_off(CS_new);
+    get_reg_off(SS_new);
+    get_reg_off(DS_new);
+    get_reg_off(FS_new);
+    get_reg_off(GS_new);
+
+    get_reg_off(pfmem08_0);
+    get_reg_off(pfmem08_1);
+    get_reg_off(pfmem08_2);
+    get_reg_off(pfmem08_3);
+    get_reg_off(pfmem08_4);
+    get_reg_off(pfmem08_5);
+    get_reg_off(pfmem08_6);
+    get_reg_off(pfmem08_7);
+    get_reg_off(pfmem08_8);
+    get_reg_off(pfmem08_9);
+    get_reg_off(pfmem08_10);
+    get_reg_off(pfmem08_11);
+    get_reg_off(pfmem08_12);
+    get_reg_off(pfmem08_13);
+    get_reg_off(pfmem08_14);
+    get_reg_off(pfmem08_15);
+    get_reg_off(pfmem08_16);
+    get_reg_off(pfmem08_17);
+    get_reg_off(pfmem08_18);
+    get_reg_off(pfmem08_19);
+    get_reg_off(pfmem16_0);
+    get_reg_off(pfmem16_1);
+    get_reg_off(pfmem16_2);
+    get_reg_off(pfmem16_3);
+    get_reg_off(pfmem16_4);
+    get_reg_off(pfmem16_5);
+    get_reg_off(pfmem16_6);
+    get_reg_off(pfmem16_7);
+    get_reg_off(pfmem16_8);
+    get_reg_off(pfmem16_9);
+    get_reg_off(pfmem16_10);
+    get_reg_off(pfmem16_11);
+    get_reg_off(pfmem16_12);
+    get_reg_off(pfmem16_13);
+    get_reg_off(pfmem16_14);
+    get_reg_off(pfmem16_15);
+    get_reg_off(pfmem16_16);
+    get_reg_off(pfmem16_17);
+    get_reg_off(pfmem16_18);
+    get_reg_off(pfmem16_19);
+    get_reg_off(pfmem32_0);
+    get_reg_off(pfmem32_1);
+    get_reg_off(pfmem32_2);
+    get_reg_off(pfmem32_3);
+    get_reg_off(pfmem32_4);
+    get_reg_off(pfmem32_5);
+    get_reg_off(pfmem32_6);
+    get_reg_off(pfmem32_7);
+    get_reg_off(pfmem32_8);
+    get_reg_off(pfmem32_9);
+    get_reg_off(pfmem32_10);
+    get_reg_off(pfmem32_11);
+    get_reg_off(pfmem32_12);
+    get_reg_off(pfmem32_13);
+    get_reg_off(pfmem32_14);
+    get_reg_off(pfmem32_15);
+    get_reg_off(pfmem32_16);
+    get_reg_off(pfmem32_17);
+    get_reg_off(pfmem32_18);
+    get_reg_off(pfmem32_19);
+    get_reg_off(pfmem64_0);
+    get_reg_off(pfmem64_1);
+    get_reg_off(pfmem64_2);
+    get_reg_off(pfmem64_3);
+    get_reg_off(pfmem64_4);
+    get_reg_off(pfmem64_5);
+    get_reg_off(pfmem64_6);
+    get_reg_off(pfmem64_7);
+    get_reg_off(pfmem64_8);
+    get_reg_off(pfmem64_9);
+    get_reg_off(pfmem64_10);
+    get_reg_off(pfmem64_11);
+    get_reg_off(pfmem64_12);
+    get_reg_off(pfmem64_13);
+    get_reg_off(pfmem64_14);
+    get_reg_off(pfmem64_15);
+    get_reg_off(pfmem64_16);
+    get_reg_off(pfmem64_17);
+    get_reg_off(pfmem64_18);
+    get_reg_off(pfmem64_19);
+
+    get_reg_off(MM0);
+    get_reg_off(MM1);
+    get_reg_off(MM2);
+    get_reg_off(MM3);
+    get_reg_off(MM4);
+    get_reg_off(MM5);
+    get_reg_off(MM6);
+    get_reg_off(MM7);
+    get_reg_off(MM0_new);
+    get_reg_off(MM1_new);
+    get_reg_off(MM2_new);
+    get_reg_off(MM3_new);
+    get_reg_off(MM4_new);
+    get_reg_off(MM5_new);
+    get_reg_off(MM6_new);
+    get_reg_off(MM7_new);
+    return dict;
+}
+
+
+static PyGetSetDef JitCpu_getseters[] = {
+    {"cpu",
+     (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu,
+     "first name",
+     NULL},
+
+    {"RAX", (getter)JitCpu_get_RAX, (setter)JitCpu_set_RAX, "RAX", NULL},
+    {"RBX", (getter)JitCpu_get_RBX, (setter)JitCpu_set_RBX, "RBX", NULL},
+    {"RCX", (getter)JitCpu_get_RCX, (setter)JitCpu_set_RCX, "RCX", NULL},
+    {"RDX", (getter)JitCpu_get_RDX, (setter)JitCpu_set_RDX, "RDX", NULL},
+    {"RSI", (getter)JitCpu_get_RSI, (setter)JitCpu_set_RSI, "RSI", NULL},
+    {"RDI", (getter)JitCpu_get_RDI, (setter)JitCpu_set_RDI, "RDI", NULL},
+    {"RSP", (getter)JitCpu_get_RSP, (setter)JitCpu_set_RSP, "RSP", NULL},
+    {"RBP", (getter)JitCpu_get_RBP, (setter)JitCpu_set_RBP, "RBP", NULL},
+    {"R8",  (getter)JitCpu_get_R8,  (setter)JitCpu_set_R8,  "R8",  NULL},
+    {"R9",  (getter)JitCpu_get_R9,  (setter)JitCpu_set_R9,  "R9",  NULL},
+    {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL},
+    {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL},
+    {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL},
+    {"R13", (getter)JitCpu_get_R13, (setter)JitCpu_set_R13, "R13", NULL},
+    {"R14", (getter)JitCpu_get_R14, (setter)JitCpu_set_R14, "R14", NULL},
+    {"R15", (getter)JitCpu_get_R15, (setter)JitCpu_set_R15, "R15", NULL},
+    {"RIP", (getter)JitCpu_get_RIP, (setter)JitCpu_set_RIP, "RIP", NULL},
+    {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL},
+    {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL},
+    {"pf", (getter)JitCpu_get_pf, (setter)JitCpu_set_pf, "pf", NULL},
+    {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL},
+    {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL},
+    {"af", (getter)JitCpu_get_af, (setter)JitCpu_set_af, "af", NULL},
+    {"df", (getter)JitCpu_get_df, (setter)JitCpu_set_df, "df", NULL},
+    {"ES", (getter)JitCpu_get_ES, (setter)JitCpu_set_ES, "ES", NULL},
+    {"CS", (getter)JitCpu_get_CS, (setter)JitCpu_set_CS, "CS", NULL},
+    {"SS", (getter)JitCpu_get_SS, (setter)JitCpu_set_SS, "SS", NULL},
+    {"DS", (getter)JitCpu_get_DS, (setter)JitCpu_set_DS, "DS", NULL},
+    {"FS", (getter)JitCpu_get_FS, (setter)JitCpu_set_FS, "FS", NULL},
+    {"GS", (getter)JitCpu_get_GS, (setter)JitCpu_set_GS, "GS", NULL},
+
+    {"EAX", (getter)JitCpu_get_EAX, (setter)JitCpu_set_EAX, "EAX", NULL},
+    {"EBX", (getter)JitCpu_get_EBX, (setter)JitCpu_set_EBX, "EBX", NULL},
+    {"ECX", (getter)JitCpu_get_ECX, (setter)JitCpu_set_ECX, "ECX", NULL},
+    {"EDX", (getter)JitCpu_get_EDX, (setter)JitCpu_set_EDX, "EDX", NULL},
+    {"ESI", (getter)JitCpu_get_ESI, (setter)JitCpu_set_ESI, "ESI", NULL},
+    {"EDI", (getter)JitCpu_get_EDI, (setter)JitCpu_set_EDI, "EDI", NULL},
+    {"ESP", (getter)JitCpu_get_ESP, (setter)JitCpu_set_ESP, "ESP", NULL},
+    {"EBP", (getter)JitCpu_get_EBP, (setter)JitCpu_set_EBP, "EBP", NULL},
+    {"EIP", (getter)JitCpu_get_EIP, (setter)JitCpu_set_EIP, "EIP", NULL},
+
+    {"AX", (getter)JitCpu_get_AX, (setter)JitCpu_set_AX, "AX", NULL},
+    {"BX", (getter)JitCpu_get_BX, (setter)JitCpu_set_BX, "BX", NULL},
+    {"CX", (getter)JitCpu_get_CX, (setter)JitCpu_set_CX, "CX", NULL},
+    {"DX", (getter)JitCpu_get_DX, (setter)JitCpu_set_DX, "DX", NULL},
+    {"SI", (getter)JitCpu_get_SI, (setter)JitCpu_set_SI, "SI", NULL},
+    {"DI", (getter)JitCpu_get_DI, (setter)JitCpu_set_DI, "DI", NULL},
+    {"SP", (getter)JitCpu_get_SP, (setter)JitCpu_set_SP, "SP", NULL},
+    {"BP", (getter)JitCpu_get_BP, (setter)JitCpu_set_BP, "BP", NULL},
+
+
+    {NULL}  /* Sentinel */
+};
+
+
+static PyTypeObject JitCpuType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "JitCore_x86.JitCpu",   /*tp_name*/
+    sizeof(JitCpu),            /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)JitCpu_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "JitCpu objects",          /* tp_doc */
+    0,			       /* tp_traverse */
+    0,			       /* tp_clear */
+    0,			       /* tp_richcompare */
+    0,			       /* tp_weaklistoffset */
+    0,			       /* tp_iter */
+    0,			       /* tp_iternext */
+    JitCpu_methods,            /* tp_methods */
+    JitCpu_members,            /* tp_members */
+    JitCpu_getseters,          /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)JitCpu_init,     /* tp_init */
+    0,                         /* tp_alloc */
+    JitCpu_new,                /* tp_new */
+};
+
+
+
+static PyMethodDef JitCore_x86_Methods[] = {
+
+	/*
+
+	*/
+	{"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS},
+	{NULL, NULL, 0, NULL}        /* Sentinel */
+
+};
+
+static PyObject *JitCore_x86_Error;
+
+PyMODINIT_FUNC
+initJitCore_x86(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&JitCpuType) < 0)
+	return;
+
+    m = Py_InitModule("JitCore_x86", JitCore_x86_Methods);
+    if (m == NULL)
+	    return;
+
+    JitCore_x86_Error = PyErr_NewException("JitCore_x86.error", NULL, NULL);
+    Py_INCREF(JitCore_x86_Error);
+    PyModule_AddObject(m, "error", JitCore_x86_Error);
+
+    Py_INCREF(&JitCpuType);
+    PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miasm2/jitter/arch/JitCore_x86.h b/miasm2/jitter/arch/JitCore_x86.h
new file mode 100644
index 00000000..7d4379a8
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_x86.h
@@ -0,0 +1,293 @@
+
+typedef struct {
+	uint32_t exception_flags;
+	uint32_t exception_flags_new;
+
+
+	/* gpregs */
+	uint64_t RAX;
+	uint64_t RBX;
+	uint64_t RCX;
+	uint64_t RDX;
+	uint64_t RSI;
+	uint64_t RDI;
+	uint64_t RSP;
+	uint64_t RBP;
+	uint64_t R8;
+	uint64_t R9;
+	uint64_t R10;
+	uint64_t R11;
+	uint64_t R12;
+	uint64_t R13;
+	uint64_t R14;
+	uint64_t R15;
+
+	uint64_t RIP;
+
+	uint64_t RAX_new;
+	uint64_t RBX_new;
+	uint64_t RCX_new;
+	uint64_t RDX_new;
+	uint64_t RSI_new;
+	uint64_t RDI_new;
+	uint64_t RSP_new;
+	uint64_t RBP_new;
+	uint64_t R8_new;
+	uint64_t R9_new;
+	uint64_t R10_new;
+	uint64_t R11_new;
+	uint64_t R12_new;
+	uint64_t R13_new;
+	uint64_t R14_new;
+	uint64_t R15_new;
+
+	uint64_t RIP_new;
+
+	/* eflag */
+	uint64_t zf;
+	uint64_t nf;
+	uint64_t pf;
+	uint64_t of;
+	uint64_t cf;
+	uint64_t af;
+	uint64_t df;
+
+	uint64_t zf_new;
+	uint64_t nf_new;
+	uint64_t pf_new;
+	uint64_t of_new;
+	uint64_t cf_new;
+	uint64_t af_new;
+	uint64_t df_new;
+
+	uint64_t tf;
+	uint64_t i_f;
+	uint64_t iopl_f;
+	uint64_t nt;
+	uint64_t rf;
+	uint64_t vm;
+	uint64_t ac;
+	uint64_t vif;
+	uint64_t vip;
+	uint64_t i_d;
+
+	uint64_t tf_new;
+	uint64_t i_f_new;
+	uint64_t iopl_f_new;
+	uint64_t nt_new;
+	uint64_t rf_new;
+	uint64_t vm_new;
+	uint64_t ac_new;
+	uint64_t vif_new;
+	uint64_t vip_new;
+	uint64_t i_d_new;
+
+	uint64_t my_tick;
+
+	uint64_t cond;
+
+	double float_st0;
+	double float_st1;
+	double float_st2;
+	double float_st3;
+	double float_st4;
+	double float_st5;
+	double float_st6;
+	double float_st7;
+
+	double float_st0_new;
+	double float_st1_new;
+	double float_st2_new;
+	double float_st3_new;
+	double float_st4_new;
+	double float_st5_new;
+	double float_st6_new;
+	double float_st7_new;
+
+	unsigned int float_c0;
+	unsigned int float_c1;
+	unsigned int float_c2;
+	unsigned int float_c3;
+
+	unsigned int float_c0_new;
+	unsigned int float_c1_new;
+	unsigned int float_c2_new;
+	unsigned int float_c3_new;
+
+	unsigned int float_stack_ptr;
+	unsigned int float_stack_ptr_new;
+
+	unsigned int reg_float_control;
+	unsigned int reg_float_control_new;
+
+	unsigned int reg_float_eip;
+	unsigned int reg_float_eip_new;
+	unsigned int reg_float_cs;
+	unsigned int reg_float_cs_new;
+	unsigned int reg_float_address;
+	unsigned int reg_float_address_new;
+	unsigned int reg_float_ds;
+	unsigned int reg_float_ds_new;
+
+
+	unsigned int tsc1;
+	unsigned int tsc2;
+
+	unsigned int tsc1_new;
+	unsigned int tsc2_new;
+
+
+	uint64_t ES;
+	uint64_t CS;
+	uint64_t SS;
+	uint64_t DS;
+	uint64_t FS;
+	uint64_t GS;
+
+	uint64_t ES_new;
+	uint64_t CS_new;
+	uint64_t SS_new;
+	uint64_t DS_new;
+	uint64_t FS_new;
+	uint64_t GS_new;
+
+	unsigned int cr0;
+	unsigned int cr0_new;
+
+	unsigned int cr3;
+	unsigned int cr3_new;
+
+
+
+	uint8_t pfmem08_0;
+	uint8_t pfmem08_1;
+	uint8_t pfmem08_2;
+	uint8_t pfmem08_3;
+	uint8_t pfmem08_4;
+	uint8_t pfmem08_5;
+	uint8_t pfmem08_6;
+	uint8_t pfmem08_7;
+	uint8_t pfmem08_8;
+	uint8_t pfmem08_9;
+	uint8_t pfmem08_10;
+	uint8_t pfmem08_11;
+	uint8_t pfmem08_12;
+	uint8_t pfmem08_13;
+	uint8_t pfmem08_14;
+	uint8_t pfmem08_15;
+	uint8_t pfmem08_16;
+	uint8_t pfmem08_17;
+	uint8_t pfmem08_18;
+	uint8_t pfmem08_19;
+
+
+	uint16_t pfmem16_0;
+	uint16_t pfmem16_1;
+	uint16_t pfmem16_2;
+	uint16_t pfmem16_3;
+	uint16_t pfmem16_4;
+	uint16_t pfmem16_5;
+	uint16_t pfmem16_6;
+	uint16_t pfmem16_7;
+	uint16_t pfmem16_8;
+	uint16_t pfmem16_9;
+	uint16_t pfmem16_10;
+	uint16_t pfmem16_11;
+	uint16_t pfmem16_12;
+	uint16_t pfmem16_13;
+	uint16_t pfmem16_14;
+	uint16_t pfmem16_15;
+	uint16_t pfmem16_16;
+	uint16_t pfmem16_17;
+	uint16_t pfmem16_18;
+	uint16_t pfmem16_19;
+
+
+	uint32_t pfmem32_0;
+	uint32_t pfmem32_1;
+	uint32_t pfmem32_2;
+	uint32_t pfmem32_3;
+	uint32_t pfmem32_4;
+	uint32_t pfmem32_5;
+	uint32_t pfmem32_6;
+	uint32_t pfmem32_7;
+	uint32_t pfmem32_8;
+	uint32_t pfmem32_9;
+	uint32_t pfmem32_10;
+	uint32_t pfmem32_11;
+	uint32_t pfmem32_12;
+	uint32_t pfmem32_13;
+	uint32_t pfmem32_14;
+	uint32_t pfmem32_15;
+	uint32_t pfmem32_16;
+	uint32_t pfmem32_17;
+	uint32_t pfmem32_18;
+	uint32_t pfmem32_19;
+
+
+	uint64_t pfmem64_0;
+	uint64_t pfmem64_1;
+	uint64_t pfmem64_2;
+	uint64_t pfmem64_3;
+	uint64_t pfmem64_4;
+	uint64_t pfmem64_5;
+	uint64_t pfmem64_6;
+	uint64_t pfmem64_7;
+	uint64_t pfmem64_8;
+	uint64_t pfmem64_9;
+	uint64_t pfmem64_10;
+	uint64_t pfmem64_11;
+	uint64_t pfmem64_12;
+	uint64_t pfmem64_13;
+	uint64_t pfmem64_14;
+	uint64_t pfmem64_15;
+	uint64_t pfmem64_16;
+	uint64_t pfmem64_17;
+	uint64_t pfmem64_18;
+	uint64_t pfmem64_19;
+
+
+	uint64_t MM0;
+	uint64_t MM1;
+	uint64_t MM2;
+	uint64_t MM3;
+	uint64_t MM4;
+	uint64_t MM5;
+	uint64_t MM6;
+	uint64_t MM7;
+
+	uint64_t MM0_new;
+	uint64_t MM1_new;
+	uint64_t MM2_new;
+	uint64_t MM3_new;
+	uint64_t MM4_new;
+	uint64_t MM5_new;
+	uint64_t MM6_new;
+	uint64_t MM7_new;
+
+	uint32_t segm_base[0x10000];
+
+}vm_cpu_t;
+
+
+
+void dump_gpregs(vm_cpu_t* vmcpu);
+uint64_t segm2addr(vm_cpu_t* vmcpu, uint64_t segm, uint64_t addr);
+
+
+uint32_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b);
+uint32_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b);
+int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b);
+int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b);
+
+uint16_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b);
+uint16_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b);
+int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b);
+int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b);
+
+uint8_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b);
+uint8_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b);
+int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b);
+int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b);
+
+#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->RIP);
diff --git a/miasm2/jitter/arch/__init__.py b/miasm2/jitter/arch/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/miasm2/jitter/arch/__init__.py
diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py
new file mode 100644
index 00000000..e4b315e1
--- /dev/null
+++ b/miasm2/jitter/csts.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+
+# VM Mngr Exceptions
+EXCEPT_DO_NOT_UPDATE_PC = 1 << 25
+
+EXCEPT_CODE_AUTOMOD = (1 << 0)
+EXCEPT_SOFT_BP = (1 << 1)
+EXCEPT_INT_XX = (1 << 2)
+EXCEPT_BREAKPOINT_INTERN = (1 << 10)
+
+EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC)
+# VM Mngr constants
+
+PAGE_READ = 1
+PAGE_WRITE = 2
+PAGE_EXEC = 4
+
+BREAKPOINT_READ = 1
+BREAKPOINT_WRITE = 2
+
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
new file mode 100644
index 00000000..34ae3be9
--- /dev/null
+++ b/miasm2/jitter/jitcore.py
@@ -0,0 +1,252 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm2.core import asmbloc
+from miasm2.core.interval import interval
+from csts import *
+
+
+class JitCore(object):
+
+    "JiT management. This is an abstract class"
+
+    def __init__(self, my_ir, bs=None):
+        """Initialise a JitCore instance.
+        @my_ir: ir instance for current architecture
+        @bs: bitstream
+        """
+
+        self.my_ir = my_ir
+        self.bs = bs
+        self.known_blocs = {}
+        self.lbl2jitbloc = {}
+        self.lbl2bloc = {}
+        self.log_mn = False
+        self.log_regs = False
+        self.log_newbloc = False
+        self.segm_to_do = set()
+        self.job_done = set()
+        self.jitcount = 0
+        self.addr2obj = {}
+        self.addr2objref = {}
+        self.blocs_mem_interval = interval()
+        self.disasm_cb = None
+        self.split_dis = set()
+
+        self.options = {"jit_maxline": 50  # Maximum number of line jitted
+                        }
+
+    def set_options(self, **kwargs):
+        "Set options relative to the backend"
+
+        self.options.update(kwargs)
+
+    def add_disassembly_splits(self, *args):
+        """The disassembly engine will stop on address in args if they
+        are not at the block beginning"""
+        self.split_dis.update(set(args))
+
+    def remove_disassembly_splits(self, *args):
+        """The disassembly engine will no longer stop on address in args"""
+        self.split_dis.difference_update(set(args))
+
+    def load(self, arch, attrib):
+        "Initialise the Jitter according to arch and attrib"
+
+        raise Exception("DO NOT instanciate JitCore")
+
+    def __get_bloc_min_max(self, cur_bloc):
+        "Update cur_bloc to set min/max address"
+
+        if cur_bloc.lines:
+            cur_bloc.ad_min = cur_bloc.lines[0].offset
+            cur_bloc.ad_max = cur_bloc.lines[-1].offset + cur_bloc.lines[-1].l
+
+    def __add_bloc_to_mem_interval(self, vm, bloc):
+        "Update vm to include bloc addresses in its memory range"
+
+        self.blocs_mem_interval += interval([(bloc.ad_min, bloc.ad_max - 1)])
+
+        vm.vm_reset_code_bloc_pool()
+        for a, b in self.blocs_mem_interval:
+            vm.vm_add_code_bloc(a, b + 1)
+
+    def jitirblocs(self, label, irblocs):
+        """JiT a group of irblocs.
+        @label: the label of the irblocs
+        @irblocs: a gorup of irblocs
+        """
+
+        raise Exception("DO NOT instanciate JitCore")
+
+    def add_bloc(self, b):
+        """Add a bloc to JiT and JiT it.
+        @b: the bloc to add
+        """
+
+        irblocs = self.my_ir.add_bloc(b, gen_pc_updt = True)
+        b.irblocs = irblocs
+        self.jitirblocs(b.label, irblocs)
+
+    def __disbloc(self, addr, cpu, vm):
+        "Disassemble a new bloc and JiT it"
+
+        # Get the bloc
+        if isinstance(addr, asmbloc.asm_label):
+            addr = addr.offset
+
+        l = self.my_ir.symbol_pool.getby_offset_create(addr)
+        cur_bloc = asmbloc.asm_bloc(l)
+
+        # Disassemble it
+        try:
+            asmbloc.dis_bloc(self.my_ir.arch, self.bs, cur_bloc, addr,
+                             set(), self.my_ir.symbol_pool, [],
+                             follow_call=False, patch_instr_symb=True,
+                             dontdis_retcall=False,
+                             lines_wd=self.options["jit_maxline"],
+                             # max 10 asm lines
+                             attrib=self.my_ir.attrib,
+                             split_dis=self.split_dis)
+        except IOError:
+            # vm_exception_flag is set
+            pass
+
+        # Logging
+        if self.log_newbloc:
+            print cur_bloc
+        if self.disasm_cb is not None:
+            self.disasm_cb(cur_bloc)
+        # Update label -> bloc
+        self.lbl2bloc[l] = cur_bloc
+
+        # Store min/max bloc address needed in jit automod code
+        self.__get_bloc_min_max(cur_bloc)
+
+        # JiT it
+        self.add_bloc(cur_bloc)
+
+        # Update jitcode mem range
+        self.__add_bloc_to_mem_interval(vm, cur_bloc)
+
+    def jit_call(self, label, cpu, vmmngr):
+        """Call the function label with cpu and vmmngr states
+        @label: function's label
+        @cpu: address of the cpu state structure
+        @vmmngr: address of the memory state structure
+        """
+
+        fc_ptr = self.lbl2jitbloc[label]
+        return self.exec_wrapper(fc_ptr, cpu, vmmngr)
+
+    def runbloc(self, cpu, vm, lbl):
+        """Run the bloc starting at lbl.
+        @cpu: JitCpu instance
+        @vm: VmMngr instance
+        @lbl: target label
+        """
+
+        if lbl is None:
+            lbl = cpu.vm_get_gpreg()[self.my_ir.pc.name]
+
+        if not lbl in self.lbl2jitbloc:
+            # Need to JiT the bloc
+            self.__disbloc(lbl, cpu, vm)
+
+        # Run the bloc and update cpu/vmmngr state
+        ret = self.jit_call(lbl, cpu.cpu, vm.vmmngr)
+
+        return ret
+
+    def __blocs2memrange(self, blocs):
+        """Return an interval instance standing for blocs addresses
+        @blocs: list of asm_bloc instances
+        """
+
+        mem_range = interval()
+
+        for b in blocs:
+            mem_range += interval([(b.ad_min, b.ad_max - 1)])
+
+        return mem_range
+
+    def __updt_jitcode_mem_range(self, vm):
+        """Rebuild the VM blocs address memory range
+        @vm: VmMngr instance
+        """
+
+        # Reset the current pool
+        vm.vm_reset_code_bloc_pool()
+
+        # Add blocs in the pool
+        for a, b in self.blocs_mem_interval:
+            vm.vm_add_code_bloc(a, b + 1)
+
+    def __del_bloc_in_range(self, ad1, ad2):
+        """Find and remove jitted bloc in range [ad1, ad2].
+        Return the list of bloc removed.
+        @ad1: First address
+        @ad2: Last address
+        """
+
+        # Find concerned blocs
+        modified_blocs = set()
+        for b in self.lbl2bloc.values():
+            if not b.lines:
+                continue
+            if b.ad_max <= ad1 or b.ad_min >= ad2:
+                # Bloc not modified
+                pass
+            else:
+                # Modified blocs
+                modified_blocs.add(b)
+
+        # Generate interval to delete
+        del_interval = self.__blocs2memrange(modified_blocs)
+
+        # Remove interval from monitored interval list
+        self.blocs_mem_interval -= del_interval
+
+        # Remove modified blocs
+        for b in modified_blocs:
+            try:
+                for irbloc in b.irblocs:
+
+                    # Remove offset -> jitted bloc link
+                    if irbloc.label.offset in self.lbl2jitbloc:
+                        del(self.lbl2jitbloc[irbloc.label.offset])
+
+            except AttributeError:
+                # The bloc has never been translated in IR
+                if b.label.offset in self.lbl2jitbloc:
+                    del(self.lbl2jitbloc[b.label.offset])
+
+            # Remove label -> bloc link
+            del(self.lbl2bloc[b.label])
+
+        return modified_blocs
+
+    def updt_automod_code(self, vm, addr, size):
+        """Remove code jitted in range [addr, addr + size]
+        @vm: VmMngr instance
+        @addr: Address of modified code in sandbox
+        @size: Modification range size (in bits)
+        """
+
+        self.__del_bloc_in_range(addr, addr + size / 8)
+        self.__updt_jitcode_mem_range(vm)
+
diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py
new file mode 100644
index 00000000..f081d281
--- /dev/null
+++ b/miasm2/jitter/jitcore_llvm.py
@@ -0,0 +1,157 @@
+import os
+import importlib
+import hashlib
+try:
+    from llvmconvert import *
+except ImportError:
+    pass
+import jitcore
+import Jitllvm
+
+
+class JitCore_LLVM(jitcore.JitCore):
+
+    "JiT management, using LLVM as backend"
+
+    # Architecture dependant libraries
+    arch_dependent_libs = {"x86": "arch/JitCore_x86.so"}
+
+    def __init__(self, my_ir, bs=None):
+        super(JitCore_LLVM, self).__init__(my_ir, bs)
+
+        self.options.update({"safe_mode": False,   # Verify each function
+                             "optimise": False,     # Optimise functions
+                             "log_func": False,    # Print LLVM functions
+                             "log_assembly": False,  # Print assembly executed
+                             "cache_ir": None      # SaveDir for cached .ll
+                             })
+
+        self.exec_wrapper = Jitllvm.llvm_exec_bloc
+        self.exec_engines = []
+
+    def load(self, arch):
+
+        # Library to load within Jit context
+        libs_to_load = []
+
+        # Get the vm_mngr librairy
+        lib_dir = os.path.dirname(os.path.realpath(__file__))
+        vm_mngr_path = os.path.join(lib_dir, 'vm_mngr.so')
+        libs_to_load.append(vm_mngr_path)
+
+        # Get architecture dependant Jitcore library (if any)
+        try:
+            jit_lib = os.path.join(
+                lib_dir, self.arch_dependent_libs[arch.name])
+            libs_to_load.append(jit_lib)
+        except KeyError:
+            pass
+
+        # Create a context
+        self.context = LLVMContext_JIT(libs_to_load)
+
+        # Set the optimisation level
+        self.context.optimise_level()
+
+        # Save the current architecture parameters
+        self.arch = arch
+
+        # Get the correspondance between registers and vmcpu struct
+        mod_name = "miasm2.jitter.arch.JitCore_%s" % (arch.name)
+        mod = importlib.import_module(mod_name)
+        self.context.set_vmcpu(mod.get_gpreg_offset_all())
+
+        # Save module base
+        self.mod_base_str = str(self.context.mod)
+
+        # Set IRs transformation to apply
+        self.context.set_IR_transformation(self.my_ir.expr_fix_regs_for_mode)
+
+    def add_bloc(self, bloc):
+
+        # Search in IR cache
+        if self.options["cache_ir"] is not None:
+
+            # /!\ This part is under development
+            # Use it at your own risk
+
+            # Compute Hash : label + bloc binary
+            func_name = bloc.label.name
+            to_hash = func_name
+
+            # Get binary from bloc
+            for line in bloc.lines:
+                b = line.b
+                to_hash += b
+
+            # Compute Hash
+            md5 = hashlib.md5(to_hash).hexdigest()
+
+            # Try to load the function from cache
+            filename = self.options["cache_ir"] + md5 + ".ll"
+
+            try:
+                fcontent = open(filename)
+                content = fcontent.read()
+                fcontent.close()
+
+            except IOError:
+                content = None
+
+            if content is None:
+                # Compute the IR
+                super(JitCore_LLVM, self).add_bloc(bloc)
+
+                # Save it
+                fdest = open(filename, "w")
+                dump = str(self.context.mod.get_function_named(func_name))
+                my = "declare i16 @llvm.bswap.i16(i16) nounwind readnone\n"
+
+                fdest.write(self.mod_base_str + my + dump)
+                fdest.close()
+
+            else:
+                import llvm.core as llvm_c
+                import llvm.ee as llvm_e
+                my_mod = llvm_c.Module.from_assembly(content)
+                func = my_mod.get_function_named(func_name)
+                exec_en = llvm_e.ExecutionEngine.new(my_mod)
+                self.exec_engines.append(exec_en)
+
+                # We can use the same exec_engine
+                ptr = self.exec_engines[0].get_pointer_to_function(func)
+
+                # Store a pointer on the function jitted code
+                self.lbl2jitbloc[bloc.label.offset] = ptr
+
+        else:
+            super(JitCore_LLVM, self).add_bloc(bloc)
+
+    def jitirblocs(self, label, irblocs):
+
+        # Build a function in the context
+        func = LLVMFunction(self.context, label.name)
+
+        # Set log level
+        func.log_regs = self.log_regs
+        func.log_mn = self.log_mn
+
+        # Import irblocs
+        func.from_blocs(irblocs)
+
+        # Verify
+        if self.options["safe_mode"] is True:
+            func.verify()
+
+        # Optimise
+        if self.options["optimise"] is True:
+            func.optimise()
+
+        # Log
+        if self.options["log_func"] is True:
+            print func
+        if self.options["log_assembly"] is True:
+            print func.get_assembly()
+
+        # Store a pointer on the function jitted code
+        self.lbl2jitbloc[label.offset] = func.get_function_pointer()
diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py
new file mode 100644
index 00000000..ee33bcd0
--- /dev/null
+++ b/miasm2/jitter/jitcore_tcc.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+import os
+from miasm2.ir.ir2C import irblocs2C
+from subprocess import Popen, PIPE
+import jitcore
+from distutils.sysconfig import get_python_inc
+import Jittcc
+
+
+def jit_tcc_compil(func_name, func_code):
+    global Jittcc
+    c = Jittcc.tcc_compil(func_name, func_code)
+    return c
+
+
+class jit_tcc_code():
+
+    def __init__(self, c):
+        self.c = c
+
+    def __call__(self, cpu, vm):
+        return Jittcc.tcc_exec_bloc(self.c, cpu, vm)
+
+
+def gen_core(arch, attrib):
+    lib_dir = os.path.dirname(os.path.realpath(__file__))
+
+    txt = ""
+    txt += '#include "%s/queue.h"\n' % lib_dir
+    txt += '#include "%s/vm_mngr.h"\n' % lib_dir
+    txt += '#include "%s/arch/JitCore_%s.h"\n' % (lib_dir, arch.name)
+
+    txt += r'''
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+'''
+    return txt
+
+
+def gen_C_source(my_ir, func_code):
+    c_source = ""
+    c_source += "\n".join(func_code)
+
+    c_source = gen_core(my_ir.arch, my_ir.attrib) + c_source
+
+    c_source = """
+ #ifdef __x86_64__
+ #ifndef __LP64__
+ /*
+  for ubuntu ?!? XXX TODO
+  /!\ force 64 bit system using 64 bits libc
+  change this to __ILP32__ to do so.
+ */
+ #define __LP64__
+ #endif
+ #endif
+ """ + "#include <Python.h>\n" + c_source
+
+    return c_source
+
+
+class objref:
+
+    def __init__(self, obj):
+        self.obj = obj
+
+
+class myresolver:
+
+    def __init__(self, offset):
+        self.offset = offset
+
+    def ret(self):
+        return "return PyLong_FromUnsignedLongLong(0x%X);" % self.offset
+
+from miasm2.core.utils import keydefaultdict
+
+
+class resolver:
+
+    def __init__(self):
+        self.resolvers = keydefaultdict(myresolver)
+
+    def get_resolver(self, offset):
+        return self.resolvers[offset]
+
+
+class JitCore_Tcc(jitcore.JitCore):
+
+    "JiT management, using LibTCC as backend"
+
+    def __init__(self, my_ir, bs=None):
+        super(JitCore_Tcc, self).__init__(my_ir, bs)
+        self.resolver = resolver()
+        self.exec_wrapper = Jittcc.tcc_exec_bloc
+
+    def load(self, arch):
+        # os.path.join(os.path.dirname(os.path.realpath(__file__)), "jitter")
+        lib_dir = os.path.dirname(os.path.realpath(__file__))
+        libs = []
+        libs.append(os.path.join(lib_dir, 'vm_mngr.so'))
+        libs.append(os.path.join(lib_dir, 'arch/JitCore_%s.so' % (arch.name)))
+        libs = ';'.join(libs)
+        jittcc_path = Jittcc.__file__
+        include_dir = os.path.dirname(jittcc_path)
+        include_dir += ";" + os.path.join(include_dir, "arch")
+        # print include_dir
+
+        # XXX HACK
+        # As debian/ubuntu have moved some include files using arch directory,
+        # TCC doesn't know them, so we get the info from GCC
+        # For example /usr/include/x86_64-linux-gnu which contains limits.h
+        p = Popen(["cc", "-Wp,-v", "-E", "-"],
+                  stdout=PIPE, stderr=PIPE, stdin=PIPE)
+        p.stdin.close()
+        include_files = p.stderr.read().split('\n')
+        include_files = [x[1:]
+            for x in include_files if x.startswith(' /usr/include')]
+        include_files += [include_dir, get_python_inc()]
+
+        include_files = ";".join(include_files)
+        Jittcc.tcc_set_emul_lib_path(include_files, libs)
+
+    def jitirblocs(self, label, irblocs):
+        # irbloc = self.lbl2irbloc[lbl]
+        f_name = "bloc_%s" % label.name
+        f_declaration = \
+            'PyObject* %s(vm_cpu_t* vmcpu, vm_mngr_t* vm_mngr)' % f_name
+        out = irblocs2C(self.my_ir, self.resolver, label, irblocs,
+                        gen_exception_code=True,
+                        log_mn=self.log_mn,
+                        log_regs=self.log_regs)
+        out = [f_declaration + '{'] + out + ['}\n']
+        c_code = out
+
+        func_code = gen_C_source(self.my_ir, c_code)
+        # print func_code
+        # open('tmp_%.4d.c'%self.jitcount, "w").write(func_code)
+        self.jitcount += 1
+        mcode = jit_tcc_compil(f_name, func_code)
+        jcode = jit_tcc_code(mcode)
+        self.lbl2jitbloc[label.offset] = mcode
+        self.addr2obj[label.offset] = jcode
+        self.addr2objref[label.offset] = objref(jcode)
+        # print "ADDR2CODE", hex(b.label.offset), hex(id(jcode))
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
new file mode 100644
index 00000000..d9aca929
--- /dev/null
+++ b/miasm2/jitter/jitload.py
@@ -0,0 +1,1089 @@
+#!/usr/bin/env python
+
+import os
+from miasm2.core import asmbloc
+from collections import defaultdict
+import struct
+from elfesteem import pe
+from elfesteem import cstruct
+from elfesteem import *
+from vm_mngr import *
+from vm_mngr import VmMngr
+
+from csts import *
+from miasm2.core.utils import *
+from jitcore_tcc import JitCore_Tcc
+from jitcore_llvm import JitCore_LLVM
+from miasm2.core.bin_stream import bin_stream
+
+from miasm2.ir.ir2C import init_arch_C
+import inspect
+
+import logging
+
+log = logging.getLogger('jitload.py')
+hnd = logging.StreamHandler()
+hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
+log.addHandler(hnd)
+log.setLevel(logging.CRITICAL)
+
+"""
+name2jit = {'x86':JitCore_x86,
+            'arm':JitCore_arm,
+            'msp430':JitCore_msp430,
+            }
+"""
+
+
+def whoami():
+    return inspect.stack()[2][3]
+
+
+class bin_stream_vm(bin_stream):
+
+    def __init__(self, vm, offset=0L, base_offset=0L):
+        self.offset = offset
+        self.base_offset = base_offset
+        self.vm = vm
+
+    def getlen(self):
+        return 0xFFFFFFFFFFFFFFFF
+
+    def getbytes(self, start, l=1):
+        try:
+            s = self.vm.vm_get_mem(start + self.base_offset, l)
+        except:
+            raise IOError('cannot get mem ad', hex(start))
+        return s
+
+    def readbs(self, l=1):
+        try:
+            s = self.vm.vm_get_mem(self.offset + self.base_offset, l)
+        except:
+            raise IOError('cannot get mem ad', hex(self.offset))
+        self.offset += l
+        return s
+
+    def writebs(self, l=1):
+        raise ValueError('writebs unsupported')
+
+    def setoffset(self, val):
+        self.offset = val
+
+
+def get_import_address(e):
+    import2addr = defaultdict(set)
+    if e.DirImport.impdesc is None:
+        return import2addr
+    for s in e.DirImport.impdesc:
+        # fthunk = e.rva2virt(s.firstthunk)
+        # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s))
+        libname = s.dlldescname.name.lower()
+        for ii, imp in enumerate(s.impbynames):
+            if isinstance(imp, pe.ImportByName):
+                funcname = imp.name
+            else:
+                funcname = imp
+            # l = "    %2d %-16s" % (ii, repr(funcname))
+            import2addr[(libname, funcname)].add(
+                e.rva2virt(s.firstthunk + e._wsize * ii / 8))
+    return import2addr
+
+
+def preload_pe(vm, e, runtime_lib, patch_vm_imp=True):
+    fa = get_import_address(e)
+    dyn_funcs = {}
+    # log.debug('imported funcs: %s' % fa)
+    for (libname, libfunc), ads in fa.items():
+        for ad in ads:
+            ad_base_lib = runtime_lib.lib_get_add_base(libname)
+            ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
+
+            libname_s = canon_libname_libfunc(libname, libfunc)
+            dyn_funcs[libname_s] = ad_libfunc
+            if patch_vm_imp:
+                vm.vm_set_mem(
+                    ad, struct.pack(cstruct.size2type[e._wsize], ad_libfunc))
+    return dyn_funcs
+
+
+def get_import_address_elf(e):
+    import2addr = defaultdict(set)
+    for sh in e.sh:
+        if not hasattr(sh, 'rel'):
+            continue
+        for k, v in sh.rel.items():
+            import2addr[('xxx', k)].add(v.offset)
+    return import2addr
+
+
+def preload_elf(vm, e, runtime_lib, patch_vm_imp=True):
+    # XXX quick hack
+    fa = get_import_address_elf(e)
+    dyn_funcs = {}
+    # log.debug('imported funcs: %s' % fa)
+    for (libname, libfunc), ads in fa.items():
+        for ad in ads:
+            ad_base_lib = runtime_lib.lib_get_add_base(libname)
+            ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
+
+            libname_s = canon_libname_libfunc(libname, libfunc)
+            dyn_funcs[libname_s] = ad_libfunc
+            if patch_vm_imp:
+                log.debug('patch %s %s %s' %
+                          (hex(ad), hex(ad_libfunc), libfunc))
+                vm.vm_set_mem(
+                    ad, struct.pack(cstruct.size2type[e.size], ad_libfunc))
+    return runtime_lib, dyn_funcs
+
+
+def is_redirected_export(e, ad):
+    # test is ad points to code or dll name
+    out = ''
+    for i in xrange(0x200):
+        c = e.virt(ad + i)
+        if c == "\x00":
+            break
+        out += c
+        if not (c.isalnum() or c in "_.-+*$@&#()[]={}"):
+            return False
+    if not "." in out:
+        return False
+    i = out.find('.')
+    return out[:i], out[i + 1:]
+
+
+def get_export_name_addr_list(e):
+    out = []
+    # add func name
+    for i, n in enumerate(e.DirExport.f_names):
+        addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
+        f_name = n.name.name
+        # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva))))
+        out.append((f_name, e.rva2virt(addr.rva)))
+
+    # add func ordinal
+    for i, o in enumerate(e.DirExport.f_nameordinals):
+        addr = e.DirExport.f_address[o.ordinal]
+        # log.debug('%s %s %s' % (o.ordinal, e.DirExport.expdesc.base,
+        # hex(e.rva2virt(addr.rva))))
+        out.append(
+            (o.ordinal + e.DirExport.expdesc.base, e.rva2virt(addr.rva)))
+    return out
+
+
+def canon_libname_libfunc(libname, libfunc):
+    dn = libname.split('.')[0]
+    if type(libfunc) == str:
+        return "%s_%s" % (dn, libfunc)
+    else:
+        return str(dn), libfunc
+
+
+class libimp:
+
+    def __init__(self, lib_base_ad=0x71111000, **kargs):
+        self.name2off = {}
+        self.libbase2lastad = {}
+        self.libbase_ad = lib_base_ad
+        self.lib_imp2ad = {}
+        self.lib_imp2dstad = {}
+        self.fad2cname = {}
+        self.fad2info = {}
+        self.all_exported_lib = []
+
+    def lib_get_add_base(self, name):
+        name = name.lower().strip(' ')
+        if not "." in name:
+            log.debug('warning adding .dll to modulename')
+            name += '.dll'
+            log.debug('%s' % name)
+
+        if name in self.name2off:
+            ad = self.name2off[name]
+        else:
+            ad = self.libbase_ad
+            log.debug('new lib %s %s' % (name, hex(ad)))
+            self.name2off[name] = ad
+            self.libbase2lastad[ad] = ad + 0x1
+            self.lib_imp2ad[ad] = {}
+            self.lib_imp2dstad[ad] = {}
+            self.libbase_ad += 0x1000
+        return ad
+
+    def lib_get_add_func(self, libad, imp_ord_or_name, dst_ad=None):
+        if not libad in self.name2off.values():
+            raise ValueError('unknown lib base!', hex(libad))
+
+        # test if not ordinatl
+        # if imp_ord_or_name >0x10000:
+        #    imp_ord_or_name = vm_get_str(imp_ord_or_name, 0x100)
+        #    imp_ord_or_name = imp_ord_or_name[:imp_ord_or_name.find('\x00')]
+
+        #/!\ can have multiple dst ad
+        if not imp_ord_or_name in self.lib_imp2dstad[libad]:
+            self.lib_imp2dstad[libad][imp_ord_or_name] = set()
+        self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad)
+
+        if imp_ord_or_name in self.lib_imp2ad[libad]:
+            return self.lib_imp2ad[libad][imp_ord_or_name]
+        # log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad))
+        ad = self.libbase2lastad[libad]
+        self.libbase2lastad[libad] += 0x11  # arbitrary
+        self.lib_imp2ad[libad][imp_ord_or_name] = ad
+
+        name_inv = dict([(x[1], x[0]) for x in self.name2off.items()])
+        c_name = canon_libname_libfunc(name_inv[libad], imp_ord_or_name)
+        self.fad2cname[ad] = c_name
+        self.fad2info[ad] = libad, imp_ord_or_name
+        return ad
+
+    def check_dst_ad(self):
+        for ad in self.lib_imp2dstad:
+            all_ads = self.lib_imp2dstad[ad].values()
+            all_ads.sort()
+            for i, x in enumerate(all_ads[:-1]):
+                if x is None or all_ads[i + 1] is None:
+                    return False
+                if x + 4 != all_ads[i + 1]:
+                    return False
+        return True
+
+    def add_export_lib(self, e, name):
+        self.all_exported_lib.append(e)
+        # will add real lib addresses to database
+        if name in self.name2off:
+            ad = self.name2off[name]
+        else:
+            log.debug('new lib %s' % name)
+            ad = e.NThdr.ImageBase
+            libad = ad
+            self.name2off[name] = ad
+            self.libbase2lastad[ad] = ad + 0x1
+            self.lib_imp2ad[ad] = {}
+            self.lib_imp2dstad[ad] = {}
+            self.libbase_ad += 0x1000
+
+            ads = get_export_name_addr_list(e)
+            todo = ads
+            # done = []
+            while todo:
+                # for imp_ord_or_name, ad in ads:
+                imp_ord_or_name, ad = todo.pop()
+
+                # if export is a redirection, search redirected dll
+                # and get function real addr
+                ret = is_redirected_export(e, ad)
+                if ret:
+                    exp_dname, exp_fname = ret
+                    # log.debug('export redirection %s' % imp_ord_or_name)
+                    # log.debug('source %s %s' % (exp_dname, exp_fname))
+                    exp_dname = exp_dname + '.dll'
+                    exp_dname = exp_dname.lower()
+                    # if dll auto refes in redirection
+                    if exp_dname == name:
+                        libad_tmp = self.name2off[exp_dname]
+                        if not exp_fname in self.lib_imp2ad[libad_tmp]:
+                            # schedule func
+                            todo = [(imp_ord_or_name, ad)] + todo
+                            continue
+                    elif not exp_dname in self.name2off:
+                        raise ValueError('load %r first' % exp_dname)
+                    c_name = canon_libname_libfunc(exp_dname, exp_fname)
+                    libad_tmp = self.name2off[exp_dname]
+                    ad = self.lib_imp2ad[libad_tmp][exp_fname]
+                    # log.debug('%s' % hex(ad))
+                # if not imp_ord_or_name in self.lib_imp2dstad[libad]:
+                #    self.lib_imp2dstad[libad][imp_ord_or_name] = set()
+                # self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad)
+
+                # log.debug('new imp %s %s' % (imp_ord_or_name, hex(ad)))
+                self.lib_imp2ad[libad][imp_ord_or_name] = ad
+
+                name_inv = dict([(x[1], x[0]) for x in self.name2off.items()])
+                c_name = canon_libname_libfunc(
+                    name_inv[libad], imp_ord_or_name)
+                self.fad2cname[ad] = c_name
+                self.fad2info[ad] = libad, imp_ord_or_name
+
+    def gen_new_lib(self, e, filter=lambda x: True):
+        new_lib = []
+        for n, ad in self.name2off.items():
+            out_ads = dict()
+            for k, vs in self.lib_imp2dstad[ad].items():
+                for v in vs:
+                    out_ads[v] = k
+            all_ads = self.lib_imp2dstad[ad].values()
+            all_ads = reduce(lambda x, y: x + list(y), all_ads, [])
+            all_ads = [x for x in all_ads if filter(x)]
+            # log.debug('%s' % [hex(x) for x in all_ads])
+            all_ads.sort()
+            # first, drop None
+            if not all_ads:
+                continue
+            for i, x in enumerate(all_ads):
+                if not x in [0,  None]:
+                    break
+            all_ads = all_ads[i:]
+            while all_ads:
+                othunk = all_ads[0]
+                i = 0
+                while i + 1 < len(all_ads) and all_ads[i] + 4 == all_ads[i + 1]:
+                    i += 1
+                funcs = [out_ads[x] for x in all_ads[:i + 1]]
+                try:
+                    off = e.virt2off(othunk)
+                except pe.InvalidOffset:
+                    off = None
+                if off is not None:  # e.is_in_virt_address(othunk):
+                    new_lib.append(({"name": n,
+                                     "firstthunk": off},
+                                    funcs)
+                                   )
+                all_ads = all_ads[i + 1:]
+        return new_lib
+
+
+def vm_load_pe(vm, fname, align_s=True, load_hdr=True,
+               **kargs):
+    e = pe_init.PE(open(fname, 'rb').read(), **kargs)
+
+    aligned = True
+    for s in e.SHList:
+        if s.addr & 0xFFF:
+            aligned = False
+            break
+
+    if aligned:
+        if load_hdr:
+            hdr_len = max(0x200, e.NThdr.sectionalignment)
+            min_len = min(e.SHList[0].addr, hdr_len)
+            pe_hdr = e.content[:hdr_len]
+            pe_hdr = pe_hdr + min_len * "\x00"
+            pe_hdr = pe_hdr[:min_len]
+            vm.vm_add_memory_page(
+                e.NThdr.ImageBase, PAGE_READ | PAGE_WRITE, pe_hdr)
+        if align_s:
+            for i, s in enumerate(e.SHList[:-1]):
+                s.size = e.SHList[i + 1].addr - s.addr
+                s.rawsize = s.size
+                s.data = strpatchwork.StrPatchwork(s.data[:s.size])
+                s.offset = s.addr
+            s = e.SHList[-1]
+            s.size = (s.size + 0xfff) & 0xfffff000
+        for s in e.SHList:
+            data = str(s.data)
+            data += "\x00" * (s.size - len(data))
+            # log.debug('SECTION %s %s' % (hex(s.addr),
+            # hex(e.rva2virt(s.addr))))
+            vm.vm_add_memory_page(
+                e.rva2virt(s.addr), PAGE_READ | PAGE_WRITE, data)
+            # s.offset = s.addr
+        return e
+
+    # not aligned
+    log.warning('pe is not aligned, creating big section')
+    min_addr = None
+    max_addr = None
+    data = ""
+
+    if load_hdr:
+        data = e.content[:0x400]
+        data += (e.SHList[0].addr - len(data)) * "\x00"
+        min_addr = 0
+
+    for i, s in enumerate(e.SHList):
+        if i < len(e.SHList) - 1:
+            s.size = e.SHList[i + 1].addr - s.addr
+        s.rawsize = s.size
+        s.offset = s.addr
+
+        if min_addr is None or s.addr < min_addr:
+            min_addr = s.addr
+        if max_addr is None or s.addr + s.size > max_addr:
+            max_addr = s.addr + max(s.size, len(s.data))
+    min_addr = e.rva2virt(min_addr)
+    max_addr = e.rva2virt(max_addr)
+    log.debug('%s %s %s' %
+              (hex(min_addr), hex(max_addr), hex(max_addr - min_addr)))
+
+    vm.vm_add_memory_page(min_addr,
+                          PAGE_READ | PAGE_WRITE,
+                          (max_addr - min_addr) * "\x00")
+    for s in e.SHList:
+        log.debug('%s %s' % (hex(e.rva2virt(s.addr)), len(s.data)))
+        vm.vm_set_mem(e.rva2virt(s.addr), str(s.data))
+    return e
+
+
+def vm_load_elf(vm, fname, **kargs):
+    e = elf_init.ELF(open(fname, 'rb').read(), **kargs)
+    for p in e.ph.phlist:
+        if p.ph.type != 1:
+            continue
+        log.debug('%s %s %s' %
+                  (hex(p.ph.vaddr), hex(p.ph.offset), hex(p.ph.filesz)))
+        data = e._content[p.ph.offset:p.ph.offset + p.ph.filesz]
+        r_vaddr = p.ph.vaddr & ~0xFFF
+        data = (p.ph.vaddr - r_vaddr) * "\x00" + data
+        data += (((len(data) + 0xFFF) & ~0xFFF) - len(data)) * "\x00"
+        vm.vm_add_memory_page(r_vaddr, PAGE_READ | PAGE_WRITE, data)
+    return e
+"""
+def init_jitter(arch, attrib):
+    jitarch = name2jit[(arch.name, attrib)]
+    jitarch.vm_init_regs()
+    init_memory_page_pool()
+    init_code_bloc_pool()
+    init_memory_breakpoint()
+    jit_tcc_init(arch, attrib)
+
+def init_stack(arch, attrib, stack_size = 0x10000, stack_base = 0x1230000, **kargs):
+    jitarch = name2jit[(arch.name, attrib)]
+
+    vm_add_memory_page(stack_base, PAGE_READ|PAGE_WRITE, "\x00"*stack_size)
+    regs = jitarch.vm_get_gpreg()
+    regs[arch.sp[attrib].name] = stack_base+stack_size
+    jitarch.vm_set_gpreg(regs)
+    regs = jitarch.vm_get_gpreg()
+"""
+
+
+def vm_load_pe_lib(fname_in, libs, lib_path_base, patch_vm_imp, **kargs):
+    fname = os.path.join(lib_path_base, fname_in)
+    e = vm_load_pe(fname, **kargs)
+    libs.add_export_lib(e, fname_in)
+    # preload_pe(e, libs, patch_vm_imp)
+    return e
+
+
+def vm_load_pe_libs(libs_name, libs, lib_path_base="win_dll",
+                    patch_vm_imp=True, **kargs):
+    lib_imgs = {}
+    for fname in libs_name:
+        e = vm_load_pe_lib(fname, libs, lib_path_base, patch_vm_imp)
+        lib_imgs[fname] = e
+    return lib_imgs
+
+
+def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base="win_dll",
+                           patch_vm_imp=True, **kargs):
+    for e in lib_imgs.values():
+        preload_pe(e, libs, patch_vm_imp)
+
+
+
+class CallbackHandler(object):
+
+    "Handle a list of callback"
+
+    def __init__(self):
+        self.callbacks = {}  # Key -> [callback list]
+
+    def add_callback(self, name, callback):
+        "Add a callback to the key 'name'"
+        self.callbacks[name] = self.callbacks.get(name, []) + [callback]
+
+    def set_callback(self, name, *args):
+        "Set the list of callback for key 'name'"
+        self.callbacks[name] = args
+
+    def get_callbacks(self, name):
+        "Return the list of callbacks associated to key 'name'"
+        return self.callbacks.get(name, [])
+
+    def remove_callback(self, callback):
+        """Remove the callback from the list.
+        Return the list of empty keys (removed)"""
+
+        to_check = set()
+        for key, cb_list in self.callbacks.items():
+            try:
+                cb_list.remove(callback)
+                to_check.add(key)
+            except ValueError:
+                pass
+
+        empty_keys = []
+        for key in to_check:
+            if len(self.callbacks[key]) == 0:
+                empty_keys.append(key)
+                del(self.callbacks[key])
+
+        return empty_keys
+
+    def call_callbacks(self, name, *args):
+        """Call callbacks associated to key 'name' with arguments args. While
+        callbacks return True, continue with next callback.
+        Iterator on other results."""
+
+        res = True
+
+        for c in self.get_callbacks(name):
+            res = c(*args)
+            if res is not True:
+                yield res
+
+    def __call__(self, name, *args):
+        "Wrapper for call_callbacks"
+        return self.call_callbacks(name, *args)
+
+
+class CallbackHandlerBitflag(CallbackHandler):
+
+    "Handle a list of callback with conditions on bitflag"
+
+    def __call__(self, bitflag, *args):
+        """Call each callbacks associated with bit set in bitflag. While
+        callbacks return True, continue with next callback.
+        Iterator on other results"""
+
+        res = True
+        for b in self.callbacks.keys():
+
+            if b & bitflag != 0:
+                # If the flag matched
+                for res in self.call_callbacks(b, *args):
+                    if res is not True:
+                        yield res
+
+
+class ExceptionHandle():
+
+    "Return type for exception handler"
+
+    def __init__(self, except_flag):
+        self.except_flag = except_flag
+
+    @classmethod
+    def memoryBreakpoint(cls):
+        return cls(EXCEPT_BREAKPOINT_INTERN)
+
+    def __eq__(self, to_cmp):
+        if not isinstance(to_cmp, ExceptionHandle):
+            return False
+        return (self.except_flag == to_cmp.except_flag)
+
+
+class jitter:
+
+    "Main class for JIT handling"
+
+    def __init__(self, my_ir, jit_type="tcc"):
+        """Init an instance of jitter.
+        @my_ir: ir instance for this architecture
+        @jit_type: JiT backend to use. Available options are:
+            - "tcc"
+            - "llvm"
+        """
+
+        self.arch = my_ir.arch
+        self.attrib = my_ir.attrib
+        arch_name = my_ir.arch.name  # (my_ir.arch.name, my_ir.attrib)
+        if arch_name == "x86":
+            from arch import JitCore_x86 as jcore
+        elif arch_name == "arm":
+            from arch import JitCore_arm as jcore
+        elif arch_name == "msp430":
+            from arch import JitCore_msp430 as jcore
+        else:
+            raise ValueError("unsupported jit arch!")
+
+        self.cpu = jcore.JitCpu()
+        self.vm = VmMngr()
+        self.bs = bin_stream_vm(self.vm)
+        self.my_ir = my_ir
+        init_arch_C(self.arch)
+
+        if jit_type == "tcc":
+            self.jit = JitCore_Tcc(self.my_ir, self.bs)
+        elif jit_type == "llvm":
+            self.jit = JitCore_LLVM(self.my_ir, self.bs)
+        else:
+            raise Exception("Unkown JiT Backend")
+
+        self.cpu.vm_init_regs()
+        self.vm.vm_init_memory_page_pool()
+        self.vm.vm_init_code_bloc_pool()
+        self.vm.vm_init_memory_breakpoint()
+
+        self.vm.vm_set_addr2obj(self.jit.addr2obj)
+
+        self.jit.load(self.arch)
+        self.stack_size = 0x10000
+        self.stack_base = 0x1230000
+
+        # Init callback handler
+        self.breakpoints_handler = CallbackHandler()
+        self.exceptions_handler = CallbackHandlerBitflag()
+        self.init_exceptions_handler()
+        self.exec_cb = None
+
+    def init_exceptions_handler(self):
+        "Add common exceptions handlers"
+
+        def exception_automod(jitter):
+            "Tell the JiT backend to update blocs modified"
+            addr = self.vm.vm_get_last_write_ad()
+            size = self.vm.vm_get_last_write_size()
+
+            self.jit.updt_automod_code(self.vm, addr, size)
+            self.vm.vm_set_exception(0)
+
+            return True
+
+        def exception_memory_breakpoint(jitter):
+            "Stop the execution and return an identifier"
+            return ExceptionHandle.memoryBreakpoint()
+
+        self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
+        self.add_exception_handler(EXCEPT_BREAKPOINT_INTERN,
+                                   exception_memory_breakpoint)
+
+    def add_breakpoint(self, addr, callback):
+        """Add a callback associated with addr.
+        @addr: breakpoint address
+        @callback: function with definition (jitter instance)
+        """
+        self.breakpoints_handler.add_callback(addr, callback)
+        self.jit.add_disassembly_splits(addr)
+
+    def remove_breakpoints_by_callback(self, callback):
+        """Remove callbacks associated with breakpoint.
+        @callback: callback to remove
+        """
+        empty_keys = self.breakpoints_handler.remove_callback(callback)
+        for key in empty_keys:
+            self.jit.remove_disassembly_splits(key)
+
+    def add_exception_handler(self, flag, callback):
+        """Add a callback associated with an exception flag.
+        @flag: bitflag
+        @callback: function with definition (jitter instance)
+        """
+        self.exceptions_handler.add_callback(flag, callback)
+
+    def runbloc(self, pc):
+        """Wrapper on JiT backend. Run the code at PC and return the next PC.
+        @pc: address of code to run"""
+
+        return self.jit.runbloc(self.cpu, self.vm, pc)
+
+    def runiter_once(self, pc):
+        """Iterator on callbacks results on code running from PC.
+        Check exceptions before breakpoints."""
+
+        self.pc = pc
+
+        # Callback called before exec
+        if self.exec_cb is not None:
+            res = self.exec_cb(self)
+            if res is not True:
+                yield res
+
+        # Check breakpoints
+        old_pc = self.pc
+        for res in self.breakpoints_handler(self.pc, self):
+            if res is not True:
+                yield res
+
+        # If a callback changed pc, re call every callback
+        if old_pc != self.pc:
+            return
+
+        # Exceptions should never be activated before run
+        assert(self.get_exception() == 0)
+
+        # Run the bloc at PC
+        self.pc = self.runbloc(self.pc)
+
+        # Check exceptions
+        exception_flag = self.get_exception()
+        for res in self.exceptions_handler(exception_flag, self):
+            if res is not True:
+                yield res
+
+    def init_run(self, pc):
+        """Create an iterator on pc with runiter.
+        @pc: address of code to run
+        """
+        self.run_iterator = self.runiter_once(pc)
+        self.pc = pc
+        self.run = True
+
+    def continue_run(self, step=False):
+        """PRE: init_run.
+        Continue the run of the current session until iterator returns or run is
+        set to False.
+        If step is True, run only one time.
+        Return the iterator value"""
+
+        while self.run:
+            try:
+                return self.run_iterator.next()
+            except StopIteration:
+                pass
+
+            self.run_iterator = self.runiter_once(self.pc)
+
+            if step is True:
+                return None
+
+        return None
+
+    def init_stack(self):
+        self.vm.vm_add_memory_page(
+            self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size)
+        sp = self.arch.getsp(self.attrib)
+        setattr(self.cpu, sp.name, self.stack_base + self.stack_size)
+        # regs = self.cpu.vm_get_gpreg()
+        # regs[sp.name] = self.stack_base+self.stack_size
+        # self.cpu.vm_set_gpreg(regs)
+
+    def get_exception(self):
+        return self.cpu.vm_get_exception() | self.vm.vm_get_exception()
+
+    # commun functions
+    def get_str_ansi(self, addr, max_char=None):
+        """Get ansi str from vm.
+        @addr: address in memory
+        @max_char: maximum len"""
+        l = 0
+        tmp = addr
+        while ((max_char is None or l < max_char) and
+            self.vm.vm_get_mem(tmp, 1) != "\x00"):
+            tmp += 1
+            l += 1
+        return self.vm.vm_get_mem(addr, l)
+
+    def get_str_unic(self, addr, max_char=None):
+        """Get unicode str from vm.
+        @addr: address in memory
+        @max_char: maximum len"""
+        l = 0
+        tmp = addr
+        while ((max_char is None or l < max_char) and
+            self.vm.vm_get_mem(tmp, 2) != "\x00\x00"):
+            tmp += 2
+            l += 2
+        s = self.vm.vm_get_mem(addr, l)
+        s = s[::2]  # TODO: real unicode decoding
+        return s
+
+    def set_str_ansi(self, addr, s):
+        """Set an ansi string in memory"""
+        s = s + "\x00"
+        self.vm.vm_set_mem(addr, s)
+
+    def set_str_unic(self, addr, s):
+        """Set an unicode string in memory"""
+        s = "\x00".join(list(s)) + '\x00' * 3
+        self.vm.vm_set_mem(addr, s)
+
+
+class jitter_x86_16(jitter):
+
+    def __init__(self, *args, **kwargs):
+        from miasm2.arch.x86.sem import ir_x86_16
+        sp = asmbloc.asm_symbol_pool()
+        jitter.__init__(self, ir_x86_16(sp), *args, **kwargs)
+        self.my_ir.jit_pc = self.my_ir.arch.regs.RIP
+        self.my_ir.do_stk_segm = False
+        self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode
+        self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode
+
+    def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64):
+        self.orig_irbloc_fix_regs_for_mode(irbloc, 64)
+
+    def vm_push_uint16_t(self, v):
+        self.cpu.SP -= self.my_ir.sp.size / 8
+        self.vm.vm_set_mem(self.cpu.SP, pck16(v))
+
+    def vm_pop_uint16_t(self):
+        x = upck16(self.vm.vm_get_mem(self.cpu.SP, self.my_ir.sp.size / 8))
+        self.cpu.SP += self.my_ir.sp.size / 8
+        return x
+
+    def get_stack_arg(self, n):
+        x = upck16(self.vm.vm_get_mem(self.cpu.SP + 4 * n, 4))
+        return x
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.IP = self.pc
+
+
+class jitter_x86_32(jitter):
+
+    def __init__(self, *args, **kwargs):
+        from miasm2.arch.x86.sem import ir_x86_32
+        sp = asmbloc.asm_symbol_pool()
+        jitter.__init__(self, ir_x86_32(sp), *args, **kwargs)
+        self.my_ir.jit_pc = self.my_ir.arch.regs.RIP
+        self.my_ir.do_stk_segm = False
+
+        self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode
+        self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode
+
+    def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64):
+        self.orig_irbloc_fix_regs_for_mode(irbloc, 64)
+
+    def vm_push_uint32_t(self, v):
+        self.cpu.ESP -= self.my_ir.sp.size / 8
+        self.vm.vm_set_mem(self.cpu.ESP, pck32(v))
+
+    def vm_pop_uint32_t(self):
+        x = upck32(self.vm.vm_get_mem(self.cpu.ESP, self.my_ir.sp.size / 8))
+        self.cpu.ESP += self.my_ir.sp.size / 8
+        return x
+
+    def get_stack_arg(self, n):
+        x = upck32(self.vm.vm_get_mem(self.cpu.ESP + 4 * n, 4))
+        return x
+
+    # calling conventions
+
+    # stdcall
+    def func_args_stdcall(self, n_args):
+        ret_ad = self.vm_pop_uint32_t()
+        args = []
+        for _ in xrange(n_args):
+            args.append(self.vm_pop_uint32_t())
+        log.debug('%s %s %s' % (whoami(), hex(ret_ad), [hex(x) for x in args]))
+        return ret_ad, args
+
+    def func_ret_stdcall(self, ret_addr, ret_value1=None, ret_value2=None):
+        self.cpu.EIP = ret_addr
+        if ret_value1 is not None:
+            self.cpu.EAX = ret_value1
+        if ret_value2 is not None:
+            self.cpu.EDX = ret_value
+
+    # cdecl
+    def func_args_cdecl(self, n_args, dolog=True):
+        ret_ad = self.vm_pop_uint32_t()
+        args = []
+        for i in xrange(n_args):
+            args.append(self.get_stack_arg(i))
+        if dolog:
+            log.debug('%s %s %s' %
+                      (whoami(), hex(ret_ad), [hex(x) for x in args]))
+        return ret_ad, args
+
+    def func_ret_cdecl(self, ret_addr, ret_value):
+        self.cpu.EIP = ret_addr
+        self.cpu.EAX = ret_value
+
+    def add_lib_handler(self, libs, user_globals=None):
+        """Add a function to handle libs call with breakpoints
+        @libs: libimp instance
+        @user_globals: dictionnary for defined user function
+        """
+        if user_globals is None:
+            user_globals = {}
+
+        from miasm2.jitter.os_dep import win_api_x86_32
+
+        def handle_lib(jitter):
+            fname = libs.fad2cname[jitter.pc]
+            if fname in user_globals:
+                f = user_globals[fname]
+            elif fname in win_api_x86_32.__dict__:
+                f = win_api_x86_32.__dict__[fname]
+            else:
+                log.debug('%s' % repr(fname))
+                raise ValueError('unknown api', hex(jitter.vm_pop_uint32_t()), repr(fname))
+            f(jitter)
+            jitter.pc = getattr(jitter.cpu, jitter.my_ir.pc.name)
+            return True
+
+        for f_addr in libs.fad2cname:
+            self.add_breakpoint(f_addr, handle_lib)
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.EIP = self.pc
+
+
+class jitter_x86_64(jitter):
+
+    def __init__(self, *args, **kwargs):
+        from miasm2.arch.x86.sem import ir_x86_64
+        sp = asmbloc.asm_symbol_pool()
+        jitter.__init__(self, ir_x86_64(sp), *args, **kwargs)
+        self.my_ir.jit_pc = self.my_ir.arch.regs.RIP
+        self.my_ir.do_stk_segm = False
+
+        self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode
+        self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode
+
+    def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64):
+        self.orig_irbloc_fix_regs_for_mode(irbloc, 64)
+
+    def vm_push_uint64_t(self, v):
+        self.cpu.RSP -= self.my_ir.sp.size / 8
+        self.vm.vm_set_mem(self.cpu.RSP, pck64(v))
+
+    def vm_pop_uint64_t(self):
+        x = upck64(self.vm.vm_get_mem(self.cpu.RSP, self.my_ir.sp.size / 8))
+        self.cpu.RSP += self.my_ir.sp.size / 8
+        return x
+
+    def get_stack_arg(self, n):
+        x = upck64(self.vm.vm_get_mem(self.cpu.RSP + 4 * n, 4))
+        return x
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.RIP = self.pc
+
+
+class jitter_arm(jitter):
+
+    def __init__(self, *args, **kwargs):
+        from miasm2.arch.arm.sem import ir_arm
+        sp = asmbloc.asm_symbol_pool()
+        jitter.__init__(self, ir_arm(sp), *args, **kwargs)
+        self.my_ir.jit_pc = self.my_ir.arch.regs.PC
+
+    def vm_push_uint32_t(self, v):
+        self.cpu.SP -= 4
+        self.vm.vm_set_mem(self.cpu.SP, pck32(v))
+
+    def vm_pop_uint32_t(self):
+        x = upck32(self.vm.vm_get_mem(self.cpu.SP, 4))
+        self.cpu.SP += 4
+        return x
+
+    def get_stack_arg(self, n):
+        x = upck32(self.vm.vm_get_mem(self.cpu.SP + 4 * n, 4))
+        return x
+
+    # calling conventions
+
+    def func_args_fastcall(self, n_args):
+        args = []
+        for i in xrange(min(n_args, 4)):
+            args.append(self.cpu.vm_get_gpreg()['R%d' % i])
+        for i in xrange(max(0, n_args - 4)):
+            args.append(self.get_stack_arg(i))
+        log.debug('%s %s' % (whoami(), [hex(x) for x in args]))
+        return args
+
+    def func_ret_fastcall(self, ret_value=None):
+        self.pc = self.cpu.PC = self.cpu.LR
+        if ret_value is not None:
+            self.cpu.R0 = ret_value
+        return True
+
+    def add_lib_handler(self, libs):
+        from miasm2.jitter.os_dep import linux_stdlib
+        for offset, fname in libs.fad2cname.iteritems():
+            if fname in linux_stdlib.__dict__:
+                self.add_breakpoint(offset, linux_stdlib.__dict__[fname])
+            else:
+                log.warning(
+                    'jitter libhandler: %s function not found!' % fname)
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.PC = self.pc
+
+
+def vm2pe(myjit, fname, libs=None, e_orig=None,
+          max_addr=1 << 64, min_addr=0x401000,
+          min_section_offset=0x1000, img_base=None,
+          added_funcs=None):
+    mye = pe_init.PE()
+
+    if img_base is None:
+        img_base = e_orig.NThdr.ImageBase
+
+    mye.NThdr.ImageBase = img_base
+    all_mem = myjit.vm.vm_get_all_memory()
+    addrs = all_mem.keys()
+    addrs.sort()
+    mye.Opthdr.AddressOfEntryPoint = mye.virt2rva(myjit.cpu.EIP)
+    first = True
+    for ad in addrs:
+        if not min_addr <= ad < max_addr:
+            continue
+        log.debug('%s' % hex(ad))
+        if first:
+            mye.SHList.add_section(
+                "%.8X" % ad,
+                addr=ad - mye.NThdr.ImageBase,
+                data=all_mem[ad]['data'],
+                offset=min_section_offset)
+        else:
+            mye.SHList.add_section(
+                "%.8X" % ad,
+                addr=ad - mye.NThdr.ImageBase,
+                data=all_mem[ad]['data'])
+        first = False
+    if libs:
+        if added_funcs is not None:
+            # name_inv = dict([(x[1], x[0]) for x in libs.name2off.items()])
+
+            for addr, funcaddr in added_func:
+                libbase, dllname = libs.fad2info[funcaddr]
+                libs.lib_get_add_func(libbase, dllname, addr)
+
+        new_dll = libs.gen_new_lib(mye, lambda x: mye.virt.is_addr_in(x))
+    else:
+        new_dll = {}
+
+    log.debug('%s' % new_dll)
+
+    mye.DirImport.add_dlldesc(new_dll)
+    s_imp = mye.SHList.add_section("import", rawsize=len(mye.DirImport))
+    mye.DirImport.set_rva(s_imp.addr)
+    log.debug('%s' % repr(mye.SHList))
+    if e_orig:
+        # resource
+        xx = str(mye)
+        mye.content = xx
+        ad = e_orig.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva
+        log.debug('dirres %s' % hex(ad))
+        if ad != 0:
+            mye.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva = ad
+            mye.DirRes = pe.DirRes.unpack(xx, ad, mye)
+            # log.debug('%s' % repr(mye.DirRes))
+            s_res = mye.SHList.add_section(
+                name="myres", rawsize=len(mye.DirRes))
+            mye.DirRes.set_rva(s_res.addr)
+            log.debug('%s' % repr(mye.DirRes))
+    # generation
+    open(fname, 'w').write(str(mye))
+
+
+class jitter_msp430(jitter):
+
+    def __init__(self, *args, **kwargs):
+        from miasm2.arch.msp430.sem import ir_msp430
+        sp = asmbloc.asm_symbol_pool()
+        jitter.__init__(self, ir_msp430(sp), *args, **kwargs)
+        self.my_ir.jit_pc = self.my_ir.arch.regs.PC
+
+    def vm_push_uint16_t(self, v):
+        regs = self.cpu.vm_get_gpreg()
+        regs['SP'] -= 2
+        self.cpu.vm_set_gpreg(regs)
+        self.vm.vm_set_mem(regs['SP'], pck16(v))
+
+    def vm_pop_uint16_t(self):
+        regs = self.cpu.vm_get_gpreg()
+        x = upck16(self.vm.vm_get_mem(regs['SP'], 2))
+        regs['SP'] += 2
+        self.cpu.vm_set_gpreg(regs)
+        return x
+
+    def get_stack_arg(self, n):
+        regs = self.cpu.vm_get_gpreg()
+        x = upck16(self.vm.vm_get_mem(regs['SP'] + 2 * n, 2))
+        return x
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.PC = self.pc
+
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
new file mode 100644
index 00000000..406a36c9
--- /dev/null
+++ b/miasm2/jitter/llvmconvert.py
@@ -0,0 +1,982 @@
+#
+#
+# Miasm2 Extension:                                                            #
+# - Miasm2 IR to LLVM IR                                                       #
+# - JiT                                                                        #
+#
+# Requires:                                                                    #
+# - llvmpy (tested on v0.11.2)                                                 #
+#
+# Authors : Fabrice DESCLAUX (CEA/DAM), Camille MOUGEY (CEA/DAM)               #
+#
+#
+
+import llvm
+import llvm.core as llvm_c
+import llvm.ee as llvm_e
+import llvm.passes as llvm_p
+import miasm2.expression.expression as m2_expr
+import miasm2.jitter.csts as m2_csts
+import miasm2.core.asmbloc as m2_asmbloc
+
+
+class LLVMType(llvm_c.Type):
+
+    "Handle LLVM Type"
+
+    int_cache = {}
+
+    @classmethod
+    def int(cls, size=32):
+        try:
+            return cls.int_cache[size]
+        except KeyError:
+            cls.int_cache[size] = llvm_c.Type.int(size)
+            return cls.int_cache[size]
+
+    @classmethod
+    def pointer(cls, addr):
+        "Generic pointer for execution"
+        return llvm_e.GenericValue.pointer(addr)
+
+    @classmethod
+    def generic(cls, e):
+        "Generic value for execution"
+        if isinstance(e, m2_expr.ExprInt):
+            return llvm_e.GenericValue.int(LLVMType.int(e.size), int(e.arg))
+        elif isinstance(e, llvm_e.GenericValue):
+            return e
+        else:
+            raise ValueError()
+
+
+class LLVMContext():
+
+    "Context for llvm binding. Stand for a LLVM Module"
+
+    known_fc = {}
+
+    def __init__(self, name="mod"):
+        "Initialize a context with a module named 'name'"
+        self.mod = llvm_c.Module.new(name)
+        self.pass_manager = llvm_p.FunctionPassManager.new(self.mod)
+        self.exec_engine = llvm_e.ExecutionEngine.new(self.mod)
+        self.add_fc(self.known_fc)
+
+    def optimise_level(self, classic_passes=True, dead_passes=True):
+        """Set the optimisation level :
+        classic_passes :
+         - combine instruction
+         - reassociate
+         - global value numbering
+         - simplify cfg
+
+        dead_passes :
+         - dead code
+         - dead store
+         - dead instructions
+        """
+
+        # Set up the optimiser pipeline
+
+        if classic_passes is True:
+            # self.pass_manager.add(llvm_p.PASS_INSTCOMBINE)
+            self.pass_manager.add(llvm_p.PASS_REASSOCIATE)
+            self.pass_manager.add(llvm_p.PASS_GVN)
+            self.pass_manager.add(llvm_p.PASS_SIMPLIFYCFG)
+
+        if dead_passes is True:
+            self.pass_manager.add(llvm_p.PASS_DCE)
+            self.pass_manager.add(llvm_p.PASS_DSE)
+            self.pass_manager.add(llvm_p.PASS_DIE)
+
+        self.pass_manager.initialize()
+
+    def get_execengine(self):
+        "Return the Execution Engine associated with this context"
+        return self.exec_engine
+
+    def get_passmanager(self):
+        "Return the Pass Manager associated with this context"
+        return self.exec_engine
+
+    def get_module(self):
+        "Return the module associated with this context"
+        return self.mod
+
+    def add_shared_library(self, filename):
+        "Load the shared library 'filename'"
+        return llvm_c.load_library_permanently(filename)
+
+    def add_fc(self, fc):
+        "Add function into known_fc"
+
+        for name, detail in fc.items():
+            self.mod.add_function(LLVMType.function(detail["ret"],
+                                                    detail["args"]),
+                                  name)
+
+
+class LLVMContext_JIT(LLVMContext):
+
+    "Extend LLVMContext_JIT in order to handle memory management"
+
+    def __init__(self, library_filenames, name="mod"):
+        "Init a LLVMContext object, and load the mem management shared library"
+        LLVMContext.__init__(self, name)
+        for lib_fname in library_filenames:
+            self.add_shared_library(lib_fname)
+        self.add_memlookups()
+        self.add_get_exceptionflag()
+        self.add_op()
+        self.add_log_functions()
+        self.vmcpu = {}
+
+    def add_memlookups(self):
+        "Add MEM_LOOKUP functions"
+
+        fc = {}
+        p8 = llvm_c.PointerType.pointer(LLVMType.int(8))
+        for i in [8, 16, 32, 64]:
+            fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.int(i),
+                                         "args": [p8,
+                                                  LLVMType.int(64)]}
+
+            fc["MEM_WRITE_%02d" % i] = {"ret": LLVMType.void(),
+                                        "args": [p8,
+                                                 LLVMType.int(64),
+                                                 LLVMType.int(i)]}
+
+        self.add_fc(fc)
+
+    def add_get_exceptionflag(self):
+        "Add 'get_exception_flag' function"
+        p8 = llvm_c.PointerType.pointer(LLVMType.int(8))
+        self.add_fc({"get_exception_flag": {"ret": LLVMType.int(64),
+                                            "args": [p8]}})
+
+    def add_op(self):
+        "Add operations functions"
+
+        p8 = llvm_c.PointerType.pointer(LLVMType.int(8))
+        self.add_fc({"parity": {"ret": LLVMType.int(),
+                                "args": [LLVMType.int()]}})
+        self.add_fc({"rot_left": {"ret": LLVMType.int(),
+                                  "args": [LLVMType.int(),
+                                           LLVMType.int(),
+                                           LLVMType.int()]}})
+        self.add_fc({"rot_right": {"ret": LLVMType.int(),
+                                   "args": [LLVMType.int(),
+                                            LLVMType.int(),
+                                            LLVMType.int()]}})
+
+        self.add_fc({"segm2addr": {"ret": LLVMType.int(64),
+                                   "args": [p8,
+                                            LLVMType.int(64),
+                                            LLVMType.int(64)]}})
+
+        for k in [8, 16]:
+            self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.int(k),
+                                           "args": [LLVMType.int(k),
+                                                    LLVMType.int(k)]}})
+            self.add_fc({"bcdadd_cf_%s" % k: {"ret": LLVMType.int(k),
+                                              "args": [LLVMType.int(k),
+                                                       LLVMType.int(k)]}})
+
+        for k in [16, 32, 64]:
+            self.add_fc({"imod%s" % k: {"ret": LLVMType.int(k),
+                                        "args": [p8,
+                                                 LLVMType.int(k),
+                                                 LLVMType.int(k)]}})
+            self.add_fc({"idiv%s" % k: {"ret": LLVMType.int(k),
+                                        "args": [p8,
+                                                 LLVMType.int(k),
+                                                 LLVMType.int(k)]}})
+
+    def add_log_functions(self):
+        "Add functions for state logging"
+
+        p8 = llvm_c.PointerType.pointer(LLVMType.int(8))
+        self.add_fc({"dump_gpregs": {"ret": LLVMType.void(),
+                                     "args": [p8]}})
+
+    def set_vmcpu(self, lookup_table):
+        "Set the correspondance between register name and vmcpu offset"
+
+        self.vmcpu = lookup_table
+
+    def set_IR_transformation(self, *args):
+        """Set a list of transformation to apply on expression before their
+        treatments.
+        args: function Expr(Expr)"""
+        self.IR_transformation_functions = args
+
+
+class LLVMFunction():
+
+    "Represent a llvm function"
+
+    # Default logging values
+    log_mn = False
+    log_regs = False
+
+    def __init__(self, llvm_context, name="fc"):
+        "Create a new function with name fc"
+        self.llvm_context = llvm_context
+        self.mod = self.llvm_context.get_module()
+
+        self.my_args = []  # (Expr, LLVMType, Name)
+        self.ret_type = None
+        self.builder = None
+        self.entry_bbl = None
+
+        self.branch_counter = 0
+        self.name = name
+
+    def new_branch_name(self):
+        "Return a new branch name"
+
+        self.branch_counter += 1
+        return "%s" % self.branch_counter
+
+    def viewCFG(self):
+        "Show the CFG of the current function"
+        self.fc.viewCFG()
+
+    def append_basic_block(self, label):
+        """Add a new basic block to the current function.
+        @label: str or asmlabel
+        Return the corresponding LLVM Basic Block"""
+        name = self.canonize_label_name(label)
+        bbl = self.fc.append_basic_block(name)
+        self.name2bbl[label] = bbl
+
+        return bbl
+
+    def init_fc(self):
+        "Init the function"
+
+        # Build type for fc signature
+        fc_type = LLVMType.function(
+            self.ret_type, [k[1] for k in self.my_args])
+
+        # Add fc in module
+        try:
+            fc = self.mod.add_function(fc_type, self.name)
+        except llvm.LLVMException:
+            # Overwrite the previous function
+            previous_fc = self.mod.get_function_named(self.name)
+            previous_fc.delete()
+            fc = self.mod.add_function(fc_type, self.name)
+
+        # Name args
+        for i, a in enumerate(self.my_args):
+            fc.args[i].name = a[2]
+
+        # Initialize local variable pool
+        self.local_vars = {}
+        self.local_vars_pointers = {}
+        for i, a in enumerate(self.my_args):
+            self.local_vars[a[2]] = fc.args[i]
+
+        # Init cache
+        self.expr_cache = {}
+        self.main_stream = True
+        self.name2bbl = {}
+        self.offsets_jitted = set()
+
+        # Function link
+        self.fc = fc
+
+        # Add a first BasicBlock
+        self.entry_bbl = self.append_basic_block("entry")
+
+        # Instruction builder
+        self.builder = llvm_c.Builder.new(self.entry_bbl)
+
+    def CreateEntryBlockAlloca(self, var_type):
+        "Create an alloca instruction at the beginning of the current fc"
+        builder = self.builder
+        current_bbl = builder.basic_block
+        builder.position_at_end(self.entry_bbl)
+
+        ret = builder.alloca(var_type)
+        builder.position_at_end(current_bbl)
+        return ret
+
+    def get_ptr_by_expr(self, expr):
+        """"Return a pointer casted corresponding to ExprId expr. If it is not
+        already computed, compute it at the end of entry_bloc"""
+
+        name = expr.name
+
+        try:
+            # If the pointer has already been computed
+            ptr_casted = self.local_vars_pointers[name]
+
+        except KeyError:
+            # Get current objects
+            builder = self.builder
+            current_bbl = builder.basic_block
+
+            # Go at the right position
+            entry_bloc_bbl = self.entry_bbl
+            builder.position_at_end(entry_bloc_bbl)
+
+            # Compute the pointer address
+            offset = self.llvm_context.vmcpu[name]
+
+            # Pointer cast
+            ptr = builder.gep(self.local_vars["vmcpu"],
+                              [llvm_c.Constant.int(LLVMType.int(),
+                                                   offset)])
+            int_size = LLVMType.int(expr.size)
+            ptr_casted = builder.bitcast(ptr,
+                                         llvm_c.PointerType.pointer(int_size))
+            # Store in cache
+            self.local_vars_pointers[name] = ptr_casted
+
+            # Reset builder
+            builder.position_at_end(current_bbl)
+
+        return ptr_casted
+
+    def clear_cache(self, regs_updated):
+        "Remove from the cache values which depends on regs_updated"
+
+        regs_updated_set = set(regs_updated)
+
+        for expr in self.expr_cache.keys():
+            if expr.get_r(True).isdisjoint(regs_updated_set) is not True:
+                self.expr_cache.pop(expr)
+
+    def update_cache(self, name, value):
+        "Add 'name' = 'value' to the cache iff main_stream = True"
+
+        if self.main_stream is True:
+            self.expr_cache[name] = value
+
+    def add_ir(self, expr):
+        "Add a Miasm2 IR to the last bbl. Return the var created"
+
+        if self.main_stream is True and expr in self.expr_cache:
+            return self.expr_cache[expr]
+
+        builder = self.builder
+
+        if isinstance(expr, m2_expr.ExprInt):
+            ret = llvm_c.Constant.int(LLVMType.int(expr.size), int(expr.arg))
+            self.update_cache(expr, ret)
+            return ret
+
+        if isinstance(expr, m2_expr.ExprId):
+            name = expr.name
+            if not isinstance(name, str):
+                # Resolve label
+                offset = name.offset
+                ret = llvm_c.Constant.int(LLVMType.int(expr.size), offset)
+                self.update_cache(expr, ret)
+                return ret
+
+            try:
+                # If expr.name is already known (args)
+                return self.local_vars[name]
+            except KeyError:
+                pass
+
+            ptr_casted = self.get_ptr_by_expr(expr)
+
+            var = builder.load(ptr_casted, name)
+            self.update_cache(expr, var)
+            return var
+
+        if isinstance(expr, m2_expr.ExprOp):
+            op = expr.op
+
+            if op == "parity":
+                fc_ptr = self.mod.get_function_named("parity")
+                arg = builder.zext(self.add_ir(expr.args[0]),
+                                   LLVMType.int())
+                ret = builder.call(fc_ptr, [arg])
+                ret = builder.trunc(ret, LLVMType.int(expr.size))
+                self.update_cache(expr, ret)
+                return ret
+
+            if op in ["<<<", ">>>"]:
+                fc_name = "rot_left" if op == "<<<" else "rot_right"
+                fc_ptr = self.mod.get_function_named(fc_name)
+                args = [self.add_ir(arg) for arg in expr.args]
+                arg_size = expr.args[0].size
+                if arg_size < 32:
+                    # Cast args
+                    args = [builder.zext(arg, LLVMType.int(32))
+                            for arg in args]
+                arg_size_cst = llvm_c.Constant.int(LLVMType.int(),
+                                                   arg_size)
+                ret = builder.call(fc_ptr, [arg_size_cst] + args)
+                if arg_size < 32:
+                    # Cast ret
+                    ret = builder.trunc(ret, LLVMType.int(arg_size))
+                self.update_cache(expr, ret)
+                return ret
+
+            if op == "bcdadd":
+                size = expr.args[0].size
+                fc_ptr = self.mod.get_function_named("bcdadd_%s" % size)
+                args = [self.add_ir(arg) for arg in expr.args]
+                ret = builder.call(fc_ptr, args)
+                self.update_cache(expr, ret)
+                return ret
+
+            if op == "bcdadd_cf":
+                size = expr.args[0].size
+                fc_ptr = self.mod.get_function_named("bcdadd_cf_%s" % size)
+                args = [self.add_ir(arg) for arg in expr.args]
+                ret = builder.call(fc_ptr, args)
+                ret = builder.trunc(ret, LLVMType.int(expr.size))
+                self.update_cache(expr, ret)
+                return ret
+
+            if op == "-":
+                zero = llvm_c.Constant.int(LLVMType.int(expr.size),
+                                           0)
+                ret = builder.sub(zero, self.add_ir(expr.args[0]))
+                self.update_cache(expr, ret)
+                return ret
+
+            if op == "segm":
+                fc_ptr = self.mod.get_function_named("segm2addr")
+                args_casted = [builder.zext(self.add_ir(arg), LLVMType.int(64))
+                               for arg in expr.args]
+                args = [self.local_vars["vmcpu"]] + args_casted
+                ret = builder.call(fc_ptr, args)
+                ret = builder.trunc(ret, LLVMType.int(expr.size))
+                self.update_cache(expr, ret)
+                return ret
+
+            if op in ["imod", "idiv"]:
+                fc_ptr = self.mod.get_function_named(
+                    "%s%s" % (op, expr.args[0].size))
+                args_casted = [self.add_ir(arg) for arg in expr.args]
+                args = [self.local_vars["vmcpu"]] + args_casted
+                ret = builder.call(fc_ptr, args)
+                self.update_cache(expr, ret)
+                return ret
+
+            if len(expr.args) > 1:
+
+                if op == "*":
+                    callback = builder.mul
+                elif op == "+":
+                    callback = builder.add
+                elif op == "&":
+                    callback = builder.and_
+                elif op == "^":
+                    callback = builder.xor
+                elif op == "|":
+                    callback = builder.or_
+                elif op == ">>":
+                    callback = builder.lshr
+                elif op == "<<":
+                    callback = builder.shl
+                elif op == "a>>":
+                    callback = builder.ashr
+                elif op == "udiv":
+                    callback = builder.udiv
+                elif op == "umod":
+                    callback = builder.urem
+                else:
+                    raise NotImplementedError('Unknown op: %s' % op)
+
+                last = self.add_ir(expr.args[0])
+
+                for i in range(1, len(expr.args)):
+                    last = callback(last,
+                                    self.add_ir(expr.args[i]))
+
+                self.update_cache(expr, last)
+
+                return last
+
+            raise NotImplementedError()
+
+        if isinstance(expr, m2_expr.ExprMem):
+
+            fc_name = "MEM_LOOKUP_%02d" % expr.size
+            fc_ptr = self.mod.get_function_named(fc_name)
+            addr_casted = builder.zext(self.add_ir(expr.arg),
+                                       LLVMType.int(64))
+
+            ret = builder.call(fc_ptr, [self.local_vars["vmmngr"],
+                                        addr_casted])
+
+            self.update_cache(expr, ret)
+            return ret
+
+        if isinstance(expr, m2_expr.ExprCond):
+            # Compute cond
+            cond = self.add_ir(expr.cond)
+            zero_casted = llvm_c.Constant.int(LLVMType.int(expr.cond.size),
+                                              0)
+            condition_bool = builder.icmp(llvm_c.ICMP_NE, cond,
+                                          zero_casted)
+
+            # Alloc return var
+            alloca = self.CreateEntryBlockAlloca(LLVMType.int(expr.size))
+
+            # Create bbls
+            branch_id = self.new_branch_name()
+            then_block = self.append_basic_block('then%s' % branch_id)
+            else_block = self.append_basic_block('else%s' % branch_id)
+            merge_block = self.append_basic_block('ifcond%s' % branch_id)
+
+            builder.cbranch(condition_bool, then_block, else_block)
+
+            # Deactivate object caching
+            current_main_stream = self.main_stream
+            self.main_stream = False
+
+            # Then Bloc
+            builder.position_at_end(then_block)
+            then_value = self.add_ir(expr.src1)
+            builder.store(then_value, alloca)
+            builder.branch(merge_block)
+
+            # Else Bloc
+            builder.position_at_end(else_block)
+            else_value = self.add_ir(expr.src2)
+            builder.store(else_value, alloca)
+            builder.branch(merge_block)
+
+            # Merge bloc
+            builder.position_at_end(merge_block)
+            ret = builder.load(alloca)
+
+            # Reactivate object caching
+            self.main_stream = current_main_stream
+
+            self.update_cache(expr, ret)
+            return ret
+
+        if isinstance(expr, m2_expr.ExprSlice):
+
+            src = self.add_ir(expr.arg)
+
+            # Remove trailing bits
+            if expr.start != 0:
+                to_shr = llvm_c.Constant.int(LLVMType.int(expr.arg.size),
+                                             expr.start)
+                shred = builder.lshr(src,
+                                     to_shr)
+            else:
+                shred = src
+
+            # Remove leading bits
+            to_and = llvm_c.Constant.int(LLVMType.int(expr.arg.size),
+                                         (1 << (expr.stop - expr.start)) - 1)
+            anded = builder.and_(shred,
+                                 to_and)
+
+            # Cast into e.size
+            ret = builder.trunc(anded,
+                                LLVMType.int(expr.size))
+
+            self.update_cache(expr, ret)
+            return ret
+
+        if isinstance(expr, m2_expr.ExprCompose):
+
+            args = []
+
+            # Build each part
+            for arg in expr.args:
+                src, start, stop = arg
+
+                # src & (stop - start)
+                src = self.add_ir(src)
+                src_casted = builder.zext(src,
+                                          LLVMType.int(expr.size))
+                to_and = llvm_c.Constant.int(LLVMType.int(expr.size),
+                                             (1 << (stop - start)) - 1)
+                anded = builder.and_(src_casted,
+                                     to_and)
+
+                if (start != 0):
+                    # result << start
+                    to_shl = llvm_c.Constant.int(LLVMType.int(expr.size),
+                                                 start)
+                    shled = builder.shl(anded, to_shl)
+                    final = shled
+                else:
+                    # Optimisation
+                    final = anded
+
+                args.append(final)
+
+            # result = part1 | part2 | ...
+            last = args[0]
+            for i in xrange(1, len(expr.args)):
+                last = builder.or_(last, args[i])
+
+            self.update_cache(expr, last)
+            return last
+
+        raise Exception("UnkownExpression", expr.__class__.__name__)
+
+    def set_ret(self, var):
+        "Add a ret of var to the last bbl"
+        self.builder.ret(var)
+
+    def from_expr(self, expr):
+        "Build the function from an expression"
+
+        # Build function signature
+        args = expr.get_r(True)
+        for a in args:
+            if not isinstance(a, m2_expr.ExprMem):
+                self.my_args.append((a, LLVMType.int(a.size), a.name))
+
+        self.ret_type = LLVMType.int(expr.size)
+
+        # Initialise the function
+        self.init_fc()
+
+        ret = self.add_ir(expr)
+
+        self.set_ret(ret)
+
+    def affect(self, src, dst, add_new=True):
+        "Affect from M2 src to M2 dst. If add_new, add a suffix '_new' to dest"
+
+        # Source
+        src = self.add_ir(src)
+
+        # Destination
+        builder = self.builder
+        self.add_ir(m2_expr.ExprId("vmcpu"))
+
+        if isinstance(dst, m2_expr.ExprId):
+            dst_name = dst.name + "_new" if add_new else dst.name
+
+            ptr_casted = self.get_ptr_by_expr(
+                m2_expr.ExprId(dst_name, dst.size))
+            builder.store(src, ptr_casted)
+
+        elif isinstance(dst, m2_expr.ExprMem):
+            self.add_ir(dst.arg)
+
+            # Function call
+            fc_name = "MEM_WRITE_%02d" % dst.size
+            fc_ptr = self.mod.get_function_named(fc_name)
+            dst = self.add_ir(dst.arg)
+            dst_casted = builder.zext(dst, LLVMType.int(64))
+            builder.call(fc_ptr, [self.local_vars["vmmngr"],
+                                  dst_casted,
+                                  src])
+
+        else:
+            raise Exception("UnknownAffectationType")
+
+    def check_error(self, line, except_do_not_update_pc=False):
+        """Add a check for memory errors.
+        @line: Irbloc line corresponding to the current instruction
+        If except_do_not_update_pc, check only for exception which do not
+        require a pc update"""
+
+        # VmMngr "get_exception_flag" return's size
+        size = 64
+        t_size = LLVMType.int(size)
+
+        # Current address
+        pc_to_return = line.offset
+
+        # Get exception flag value
+        builder = self.builder
+        fc_ptr = self.mod.get_function_named("get_exception_flag")
+        exceptionflag = builder.call(fc_ptr, [self.local_vars["vmmngr"]])
+
+        if except_do_not_update_pc is True:
+            auto_mod_flag = m2_csts.EXCEPT_DO_NOT_UPDATE_PC
+            m2_flag = llvm_c.Constant.int(t_size, auto_mod_flag)
+            exceptionflag = builder.and_(exceptionflag, m2_flag)
+
+        # Compute cond
+        zero_casted = llvm_c.Constant.int(t_size, 0)
+        condition_bool = builder.icmp(llvm_c.ICMP_NE,
+                                      exceptionflag,
+                                      zero_casted)
+
+        # Create bbls
+        branch_id = self.new_branch_name()
+        then_block = self.append_basic_block('then%s' % branch_id)
+        merge_block = self.append_basic_block('ifcond%s' % branch_id)
+
+        builder.cbranch(condition_bool, then_block, merge_block)
+
+        # Deactivate object caching
+        current_main_stream = self.main_stream
+        self.main_stream = False
+
+        # Then Bloc
+        builder.position_at_end(then_block)
+        builder.ret(llvm_c.Constant.int(self.ret_type, pc_to_return))
+
+        builder.position_at_end(merge_block)
+
+        # Reactivate object caching
+        self.main_stream = current_main_stream
+
+    def log_instruction(self, instruction, line):
+        "Print current instruction and registers if options are set"
+
+        # Get builder
+        builder = self.builder
+
+        if self.log_mn is True:
+            print instruction # TODO
+
+        if self.log_regs is True:
+            # Call dump general purpose registers
+            fc_ptr = self.mod.get_function_named("dump_gpregs")
+            builder.call(fc_ptr, [self.local_vars["vmcpu"]])
+
+    def add_bloc(self, bloc, lines):
+        "Add a bloc of instruction in the current function"
+
+        for instruction, line in zip(bloc, lines):
+            new_reg = set()
+
+            # Check general errors only at the beggining of instruction
+            if line.offset not in self.offsets_jitted:
+                self.offsets_jitted.add(line.offset)
+                self.check_error(line)
+
+                # Log mn and registers if options is set
+                self.log_instruction(instruction, line)
+
+
+            # Pass on empty instruction
+            if len(instruction) == 0:
+                continue
+
+            for expression in instruction:
+                # Apply preinit transformation
+                for func in self.llvm_context.IR_transformation_functions:
+                    expression = func(expression)
+
+                # Treat current expression
+                self.affect(expression.src, expression.dst)
+
+                # Save registers updated
+                new_reg.update(expression.dst.get_w())
+
+            # Check for errors (without updating PC)
+            self.check_error(line, except_do_not_update_pc=True)
+
+            # new -> normal
+            reg_written = []
+            for r in new_reg:
+                if isinstance(r, m2_expr.ExprId):
+                    r_new = m2_expr.ExprId(r.name + "_new", r.size)
+                    reg_written += [r, r_new]
+                    self.affect(r_new, r, add_new=False)
+
+            # Clear cache
+            self.clear_cache(reg_written)
+            self.main_stream = True
+
+    def from_bloc(self, bloc, final_expr):
+        """Build the function from a bloc, with the dst equation.
+        Prototype : f(i8* vmcpu, i8* vmmngr)"""
+
+        # Build function signature
+        self.my_args.append((m2_expr.ExprId("vmcpu"),
+                             llvm_c.PointerType.pointer(LLVMType.int(8)),
+                             "vmcpu"))
+        self.my_args.append((m2_expr.ExprId("vmmngr"),
+                             llvm_c.PointerType.pointer(LLVMType.int(8)),
+                             "vmmngr"))
+        self.ret_type = LLVMType.int(final_expr.size)
+
+        # Initialise the function
+        self.init_fc()
+
+        # Add content
+        self.add_bloc(bloc, [])
+
+        # Finalise the function
+        self.set_ret(self.add_ir(final_expr))
+
+        raise NotImplementedError("Not tested")
+
+    def canonize_label_name(self, label):
+        """Canonize @label names to a common form.
+        @label: str or asmlabel instance"""
+        if isinstance(label, str):
+            return label
+        elif isinstance(label, m2_asmbloc.asm_label):
+            return "label_%s" % label.name
+        else:
+            raise ValueError("label must either be str or asmlabel")
+
+    def get_basic_bloc_by_label(self, label):
+        "Return the bbl corresponding to label, None otherwise"
+        return self.name2bbl.get(self.canonize_label_name(label), None)
+
+    def gen_ret_or_branch(self, dest):
+        """Manage the dest ExprId. If label, branch on it if it is known.
+        Otherwise, return the ExprId or the offset value"""
+
+        builder = self.builder
+
+        if isinstance(dest, m2_expr.ExprId):
+            dest_name = dest.name
+        elif isinstance(dest, m2_expr.ExprSlice) and \
+                isinstance(dest.arg, m2_expr.ExprId):
+            # Manage ExprId mask case
+            dest_name = dest.arg.name
+        else:
+            raise ValueError()
+
+        if not isinstance(dest_name, str):
+            label = dest_name
+            target_bbl = self.get_basic_bloc_by_label(label)
+            if target_bbl is None:
+                builder.ret(self.add_ir(dest))
+            else:
+                builder.branch(target_bbl)
+        else:
+            builder.ret(self.add_ir(dest))
+
+    def add_irbloc(self, irbloc):
+        "Add the content of irbloc at the corresponding labeled block"
+        builder = self.builder
+
+        bloc = irbloc.irs
+        dest = irbloc.dst
+        label = irbloc.label
+        lines = irbloc.lines
+
+        # Get labeled basic bloc
+        label_block = self.get_basic_bloc_by_label(label)
+        builder.position_at_end(label_block)
+
+        # Erase cache
+        self.expr_cache = {}
+
+        # Add the content of the bloc with corresponding lines
+        self.add_bloc(bloc, lines)
+
+        # Erase cache
+        self.expr_cache = {}
+
+        # Manage ret
+        for func in self.llvm_context.IR_transformation_functions:
+            dest = func(dest)
+
+        if isinstance(dest, m2_expr.ExprCond):
+            # Compute cond
+            cond = self.add_ir(dest.cond)
+            zero_casted = llvm_c.Constant.int(LLVMType.int(dest.cond.size),
+                                              0)
+            condition_bool = builder.icmp(llvm_c.ICMP_NE, cond,
+                                          zero_casted)
+
+            # Create bbls
+            branch_id = self.new_branch_name()
+            then_block = self.append_basic_block('then%s' % branch_id)
+            else_block = self.append_basic_block('else%s' % branch_id)
+
+            builder.cbranch(condition_bool, then_block, else_block)
+
+            # Then Bloc
+            builder.position_at_end(then_block)
+            self.gen_ret_or_branch(dest.src1)
+
+            # Else Bloc
+            builder.position_at_end(else_block)
+            self.gen_ret_or_branch(dest.src2)
+
+        elif isinstance(dest, m2_expr.ExprId):
+            self.gen_ret_or_branch(dest)
+
+        elif isinstance(dest, m2_expr.ExprSlice):
+            self.gen_ret_or_branch(dest)
+
+        else:
+            raise Exception("Bloc dst has to be an ExprId or an ExprCond")
+
+    def from_blocs(self, blocs):
+        """Build the function from a list of bloc (irbloc instances).
+        Prototype : f(i8* vmcpu, i8* vmmngr)"""
+
+        # Build function signature
+        self.my_args.append((m2_expr.ExprId("vmcpu"),
+                             llvm_c.PointerType.pointer(LLVMType.int(8)),
+                             "vmcpu"))
+        self.my_args.append((m2_expr.ExprId("vmmngr"),
+                             llvm_c.PointerType.pointer(LLVMType.int(8)),
+                             "vmmngr"))
+        ret_size = blocs[0].dst.size
+
+        self.ret_type = LLVMType.int(ret_size)
+
+        # Initialise the function
+        self.init_fc()
+
+        # Create basic blocks (for label branchs)
+        entry_bbl, builder = self.entry_bbl, self.builder
+
+        for irbloc in blocs:
+            name = self.canonize_label_name(irbloc.label)
+            self.append_basic_block(name)
+
+        # Add content
+        builder.position_at_end(entry_bbl)
+
+        for irbloc in blocs:
+            self.add_irbloc(irbloc)
+
+        # Branch entry_bbl on first label
+        builder.position_at_end(entry_bbl)
+        first_label_bbl = self.get_basic_bloc_by_label(blocs[0].label)
+        builder.branch(first_label_bbl)
+
+    def __str__(self):
+        "Print the llvm IR corresponding to the current module"
+
+        return str(self.fc)
+
+    def verify(self):
+        "Verify the module syntax"
+
+        return self.mod.verify()
+
+    def get_assembly(self):
+        "Return native assembly corresponding to the current module"
+
+        return self.mod.to_native_assembly()
+
+    def optimise(self):
+        "Optimise the function in place"
+        while self.llvm_context.pass_manager.run(self.fc):
+            continue
+
+    def __call__(self, *args):
+        "Eval the function with arguments args"
+
+        e = self.llvm_context.get_execengine()
+
+        genargs = [LLVMType.generic(a) for a in args]
+        ret = e.run_function(self.fc, genargs)
+
+        return ret.as_int()
+
+    def get_function_pointer(self):
+        "Return a pointer on the Jitted function"
+        e = self.llvm_context.get_execengine()
+
+        return e.get_pointer_to_function(self.fc)
+
+# TODO:
+# - Add more expressions
diff --git a/miasm2/jitter/os_dep/__init__.py b/miasm2/jitter/os_dep/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/miasm2/jitter/os_dep/__init__.py
diff --git a/miasm2/jitter/os_dep/linux_stdlib.py b/miasm2/jitter/os_dep/linux_stdlib.py
new file mode 100644
index 00000000..0a1e0bfb
--- /dev/null
+++ b/miasm2/jitter/os_dep/linux_stdlib.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+from sys import stdout
+from string import printable
+
+
+def xxx_isprint(jitter):
+    '''
+    #include <ctype.h>
+    int isprint(int c);
+
+    checks for any printable character including space.
+    '''
+    c,  = jitter.func_args_fastcall(1)
+    ret = chr(c & 0xFF) in printable and 1 or 0
+    return jitter.func_ret_fastcall(ret)
+
+
+def xxx_memcpy(jitter):
+    '''
+    #include <string.h>
+    void *memcpy(void *dest, const void *src, size_t n);
+
+    copies n bytes from memory area src to memory area dest.
+    '''
+    dest, src, n, = jitter.func_args_fastcall(3)
+    jitter.vm.vm_set_mem(dest, jitter.vm.vm_get_mem(src, n))
+    return jitter.func_ret_fastcall(dest)
+
+
+def xxx_puts(jitter):
+    '''
+    #include <stdio.h>
+    int puts(const char *s);
+
+    writes the string s and a trailing newline to stdout.
+    '''
+    s, = jitter.func_args_fastcall(1)
+    while True:
+        c = jitter.vm.vm_get_mem(s, 1)
+        s += 1
+        if c == '\x00':
+            break
+        stdout.write(c)
+    stdout.write('\n')
+    return jitter.func_ret_fastcall(1)
+
+
+def xxx_snprintf(jitter):
+    '''
+    #include <stdio.h>
+    int snprintf(char *str, size_t size, const char *format, ...);
+
+    writes to string str according to format format and at most size bytes.
+    '''
+    str, size, format, = jitter.func_args_fastcall(3)
+    curarg, output = 4, ''
+    while True:
+        c = jitter.vm.vm_get_mem(format, 1)
+        format += 1
+        if c == '\x00':
+            break
+        if c == '%':
+            token = '%'
+            while True:
+                c = jitter.vm.vm_get_mem(format, 1)
+                format += 1
+                token += c
+                if c in '%cdfsux':
+                    break
+            c = token % jitter.func_args_fastcall(curarg)[-1]
+            curarg += 1
+        output += c
+    output = output[:size - 1]
+    ret = len(output)
+    jitter.vm.vm_set_mem(str, output + '\x00')
+    return jitter.func_ret_fastcall(ret)
diff --git a/miasm2/jitter/os_dep/win_api_x86_32.py b/miasm2/jitter/os_dep/win_api_x86_32.py
new file mode 100644
index 00000000..b6813efc
--- /dev/null
+++ b/miasm2/jitter/os_dep/win_api_x86_32.py
@@ -0,0 +1,3069 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import struct
+try:
+    from Crypto.Hash import MD5, SHA
+except ImportError:
+    print "cannot find crypto, skipping"
+import inspect
+from zlib import crc32
+import os
+import stat
+import time
+from miasm2.jitter.csts import *
+from miasm2.core.utils import *
+import string
+
+
+MAX_PATH = 260
+
+
+def get_next_alloc_addr(size):
+    global alloc_ad
+    ret = winobjs.alloc_ad
+    winobjs.alloc_ad = (winobjs.alloc_ad + size + winobjs.alloc_align - 1)
+    winobjs.alloc_ad &= (0xffffffff ^ (winobjs.alloc_align - 1))
+    return ret
+
+
+def alloc_mem(myjit, msize):
+    alloc_addr = get_next_alloc_addr(msize)
+    myjit.vm.vm_add_memory_page(
+        alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * msize)
+    return alloc_addr
+
+"""
+typedef struct tagPROCESSENTRY32 {
+  DWORD     dwSize;
+  DWORD     cntUsage;
+  DWORD     th32ProcessID;
+  ULONG_PTR th32DefaultHeapID;
+  DWORD     th32ModuleID;
+  DWORD     cntThreads;
+  DWORD     th32ParentProcessID;
+  LONG      pcPriClassBase;
+  DWORD     dwFlags;
+  TCHAR     szExeFile[MAX_PATH];
+} PROCESSENTRY32, *PPROCESSENTRY32;
+"""
+
+
+access_dict = {0x0: 0,
+               0x1: 0,
+               0x2: PAGE_READ,
+               0x4: PAGE_READ | PAGE_WRITE,
+               0x10: PAGE_EXEC,
+               0x20: PAGE_EXEC | PAGE_READ,
+               0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+               0x80: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+               # 0x80: PAGE_EXECUTE_WRITECOPY
+               0x100: 0
+               }
+
+access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+
+class whandle():
+
+    def __init__(self, name, info):
+        self.name = name
+        self.info = info
+
+    def __repr__(self):
+        return '<%r %r %r>' % (self.__class__.__name__, self.name, self.info)
+
+
+class handle_generator():
+
+    def __init__(self):
+        self.offset = 600
+        self.all_handles = {}
+
+    def add(self, name, info=None):
+        self.offset += 1
+        h = whandle(name, info)
+        self.all_handles[self.offset] = h
+
+        print repr(self)
+        return self.offset
+
+    def __repr__(self):
+        out = '<%r\n' % self.__class__.__name__
+        ks = self.all_handles.keys()
+        ks.sort()
+
+        for k in ks:
+            out += "    %r %r\n" % (k, self.all_handles[k])
+        out += '>'
+        return out
+
+    def __contains__(self, e):
+        return e in self.all_handles
+
+    def __getitem__(self, item):
+        return self.all_handles.__getitem__(item)
+
+    def __delitem__(self, item):
+        self.all_handles.__delitem__(item)
+
+
+class c_winobjs:
+
+    def __init__(self):
+        self.alloc_ad = 0x20000000
+        self.alloc_align = 0x1000
+        self.handle_toolhelpsnapshot = 0xaaaa00
+        self.toolhelpsnapshot_info = {}
+        self.handle_curprocess = 0xaaaa01
+        self.dbg_present = 0
+        self.tickcount = 0
+        self.dw_pid_dummy1 = 0x111
+        self.dw_pid_explorer = 0x222
+        self.dw_pid_dummy2 = 0x333
+        self.dw_pid_cur = 0x444
+        self.module_fname_nux = None
+        self.module_name = "test.exe"
+        self.module_path = "c:\\mydir\\" + self.module_name
+        self.hcurmodule = None
+        self.module_filesize = None
+        self.getversion = 0x0A280105
+        self.getforegroundwindow = 0x333333
+        self.cryptcontext_hwnd = 0x44400
+        self.cryptcontext_bnum = 0x44000
+        self.cryptcontext_num = 0
+        self.cryptcontext = {}
+        self.phhash_crypt_md5 = 0x55555
+        self.files_hwnd = {}
+        self.windowlong_dw = 0x77700
+        self.module_cur_hwnd = 0x88800
+        self.module_file_nul = 0x999000
+        self.runtime_dll = None
+        self.current_pe = None
+        self.tls_index = 0xf
+        self.tls_values = {}
+        self.handle_pool = handle_generator()
+        self.handle_mapped = {}
+        self.hkey_handles = {0x80000001: "hkey_current_user"}
+
+        self.nt_mdl = {}
+        self.nt_mdl_ad = None
+        self.nt_mdl_cur = 0
+        self.win_event_num = 0x13370
+        self.cryptdll_md5_h = {}
+
+        self.lastwin32error = 0
+        self.mutex = {}
+        self.env_variables = {}
+        self.events_pool = {}
+        self.find_data = None
+winobjs = c_winobjs()
+
+
+process_list = [
+    [
+        0x40,  # DWORD     dwSize;
+        0,  # DWORD     cntUsage;
+        winobjs.dw_pid_dummy1,  # DWORD     th32ProcessID;
+        0x11111111,  # ULONG_PTR th32DefaultHeapID;
+        0x11111112,  # DWORD     th32ModuleID;
+        1,  # DWORD     cntThreads;
+        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
+        0xbeef,  # LONG      pcPriClassBase;
+        0x0,  # DWORD     dwFlags;
+        "dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
+    ],
+    [
+        0x40,  # DWORD     dwSize;
+        0,  # DWORD     cntUsage;
+        winobjs.dw_pid_explorer,  # DWORD     th32ProcessID;
+        0x11111111,  # ULONG_PTR th32DefaultHeapID;
+        0x11111112,  # DWORD     th32ModuleID;
+        1,  # DWORD     cntThreads;
+        4,  # DWORD     th32ParentProcessID;
+        0xbeef,  # LONG      pcPriClassBase;
+        0x0,  # DWORD     dwFlags;
+        "explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
+    ],
+
+    [
+        0x40,  # DWORD     dwSize;
+        0,  # DWORD     cntUsage;
+        winobjs.dw_pid_dummy2,  # DWORD     th32ProcessID;
+        0x11111111,  # ULONG_PTR th32DefaultHeapID;
+        0x11111112,  # DWORD     th32ModuleID;
+        1,  # DWORD     cntThreads;
+        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
+        0xbeef,  # LONG      pcPriClassBase;
+        0x0,  # DWORD     dwFlags;
+        "dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
+    ],
+
+    [
+        0x40,  # DWORD     dwSize;
+        0,  # DWORD     cntUsage;
+        winobjs.dw_pid_cur,  # DWORD     th32ProcessID;
+        0x11111111,  # ULONG_PTR th32DefaultHeapID;
+        0x11111112,  # DWORD     th32ModuleID;
+        1,  # DWORD     cntThreads;
+        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
+        0xbeef,  # LONG      pcPriClassBase;
+        0x0,  # DWORD     dwFlags;
+        winobjs.module_name  # TCHAR     szExeFile[MAX_PATH];
+    ],
+
+
+]
+
+
+def whoami():
+    return inspect.stack()[1][3]
+
+
+class hobj:
+    pass
+
+
+class mdl:
+
+    def __init__(self, ad, l):
+        self.ad = ad
+        self.l = l
+
+    def __str__(self):
+        return struct.pack('LL', self.ad, self.l)
+
+
+def get_str_ansi(myjit, ad_str, max_char=None):
+    l = 0
+    tmp = ad_str
+    while ((max_char is None or l < max_char) and
+        myjit.vm.vm_get_mem(tmp, 1) != "\x00"):
+        tmp += 1
+        l += 1
+    return myjit.vm.vm_get_mem(ad_str, l)
+
+
+def get_str_unic(myjit, ad_str, max_char=None):
+    l = 0
+    tmp = ad_str
+    while ((max_char is None or l < max_char) and
+        myjit.vm.vm_get_mem(tmp, 2) != "\x00\x00"):
+        tmp += 2
+        l += 2
+    s = myjit.vm.vm_get_mem(ad_str, l)
+    s = s[::2]  # TODO: real unicode decoding
+    return s
+
+
+def set_str_ansi(s):
+    return s + "\x00"
+
+
+def set_str_unic(s):
+    return "\x00".join(list(s)) + '\x00' * 3
+
+
+def kernel32_HeapAlloc(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    heap, flags, size = args
+
+    alloc_addr = alloc_mem(myjit, size)
+
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_HeapFree(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    heap, flags, pmem = args
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_GlobalAlloc(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    uflags, msize = args
+    alloc_addr = get_next_alloc_addr(msize)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_LocalFree(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    lpvoid, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_LocalAlloc(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    uflags, msize = args
+    alloc_addr = alloc_mem(myjit, msize)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_GlobalFree(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ad, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_IsDebuggerPresent(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.dbg_present)
+
+
+def kernel32_CreateToolhelp32Snapshot(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    dwflags, th32processid = args
+    myjit.func_ret_stdcall(ret_ad, winobjs.handle_toolhelpsnapshot)
+
+
+def kernel32_GetCurrentProcess(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.handle_curprocess)
+
+
+def kernel32_GetCurrentProcessId(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.dw_pid_cur)
+
+
+def kernel32_Process32First(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    s_handle, ad_pentry = args
+
+    pentry = struct.pack(
+        'IIIIIIIII', *process_list[0][:-1]) + process_list[0][-1]
+    myjit.vm.vm_set_mem(ad_pentry, pentry)
+    winobjs.toolhelpsnapshot_info[s_handle] = 0
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_Process32Next(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    s_handle, ad_pentry = args
+
+    winobjs.toolhelpsnapshot_info[s_handle] += 1
+    if winobjs.toolhelpsnapshot_info[s_handle] >= len(process_list):
+        ret = 0
+    else:
+        ret = 1
+        n = winobjs.toolhelpsnapshot_info[s_handle]
+        print whoami(), hex(ret_ad), '(', hex(s_handle), hex(ad_pentry), ')'
+        pentry = struct.pack(
+            'IIIIIIIII', *process_list[n][:-1]) + process_list[n][-1]
+        myjit.vm.vm_set_mem(ad_pentry, pentry)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetTickCount(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    winobjs.tickcount += 1
+    myjit.func_ret_stdcall(ret_ad, winobjs.tickcount)
+
+
+def kernel32_GetVersion(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.getversion)
+
+
+def my_GetVersionEx(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ptr_struct, = args
+
+    s = struct.pack("IIIII",
+                    0x114,  # struct size
+                    0x5,   # maj vers
+                    0x2,  # min vers
+                    0xa28,  # build nbr
+                    0x2,   # platform id
+                    )
+    t = set_str("Service pack 4")
+    t = s + (t + '\x00' * 128 * 2)[:128 * 2]
+    t += struct.pack('HHHBB', 3, 0, 0x100, 1, 0)
+    s = t
+    myjit.vm.vm_set_mem(ptr_struct, s)
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetVersionExA(myjit):
+    my_GetVersionEx(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetVersionExW(myjit):
+    my_GetVersionEx(myjit, whoami(), set_str_unic)
+
+
+def kernel32_GetPriorityClass(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hwnd, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_SetPriorityClass(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    hwnd, dwpclass = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_CloseHandle(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hwnd, = args
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def user32_GetForegroundWindow(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.getforegroundwindow)
+
+
+def user32_FindWindowA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    pclassname, pwindowname = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def user32_GetTopWindow(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hwnd, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def user32_BlockInput(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    b, = args
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptAcquireContext(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    phprov, pszcontainer, pszprovider, dwprovtype, dwflags = args
+
+    if pszprovider:
+        prov = get_str(myjit, pszprovider)
+    else:
+        prov = "NONE"
+    print 'prov:', prov
+    myjit.vm.vm_set_mem(phprov, pck32(winobjs.cryptcontext_hwnd))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptAcquireContextA(myjit):
+    advapi32_CryptAcquireContext(myjit, whoami(), get_str_ansi)
+
+
+def advapi32_CryptAcquireContextW(myjit):
+    advapi32_CryptAcquireContext(myjit, whoami(), get_str_unic)
+
+
+def advapi32_CryptCreateHash(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hprov, algid, hkey, dwflags, phhash = args
+
+    winobjs.cryptcontext_num += 1
+
+    if algid == 0x00008003:
+        print 'algo is MD5'
+        myjit.vm.vm_set_mem(
+            phhash, pck32(winobjs.cryptcontext_bnum + winobjs.cryptcontext_num))
+        winobjs.cryptcontext[
+            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj()
+        winobjs.cryptcontext[
+            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = MD5.new()
+    elif algid == 0x00008004:
+        print 'algo is SHA1'
+        myjit.vm.vm_set_mem(
+            phhash, pck32(winobjs.cryptcontext_bnum + winobjs.cryptcontext_num))
+        winobjs.cryptcontext[
+            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj()
+        winobjs.cryptcontext[
+            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = SHA.new()
+    else:
+        raise ValueError('un impl algo1')
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptHashData(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    hhash, pbdata, dwdatalen, dwflags = args
+
+    if not hhash in winobjs.cryptcontext:
+        raise ValueError("unknown crypt context")
+
+    data = myjit.vm.vm_get_mem(pbdata, dwdatalen)
+    print 'will hash %X' % dwdatalen
+    print repr(data[:10]) + "..."
+    winobjs.cryptcontext[hhash].h.update(data)
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptGetHashParam(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hhash, param, pbdata, dwdatalen, dwflags = args
+
+    if not hhash in winobjs.cryptcontext:
+        raise ValueError("unknown crypt context")
+
+    if param == 2:
+        # XXX todo: save h state?
+        h = winobjs.cryptcontext[hhash].h.digest()
+    else:
+        raise ValueError('not impl', param)
+    myjit.vm.vm_set_mem(pbdata, h)
+    myjit.vm.vm_set_mem(dwdatalen, pck32(len(h)))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptReleaseContext(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    hhash, flags = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def advapi32_CryptDeriveKey(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hprov, algid, hbasedata, dwflags, phkey = args
+
+    if algid == 0x6801:
+        print 'using DES'
+    else:
+        raise ValueError('un impl algo2')
+    h = winobjs.cryptcontext[hbasedata].h.digest()
+    print 'hash', repr(h)
+    winobjs.cryptcontext[hbasedata].h_result = h
+    myjit.vm.vm_set_mem(phkey, pck32(hbasedata))
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptDestroyHash(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hhash, = args
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def advapi32_CryptDecrypt(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hkey, hhash, final, dwflags, pbdata, pdwdatalen = args
+    raise NotImplementedError()
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_CreateFile(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(7)
+    (lpfilename, access, dwsharedmode, lpsecurityattr,
+     dwcreationdisposition, dwflagsandattr, htemplatefile) = args
+
+    fname = get_str(myjit, lpfilename)
+    print 'fname', fname
+    fname_o = fname[:]
+    ret = 0xffffffff
+
+    # test if file is original binary
+    f = fname_o
+    """
+    if "\\" in fname_o:
+        f = fname_o[fname_o.rfind('\\')+1:]
+    else:
+        f = fname_o
+    """
+    print f.lower(), winobjs.module_path.lower()
+    is_original_file = f.lower() == winobjs.module_path.lower()
+
+    if fname.upper() in [r"\\.\SICE", r"\\.\NTICE", r"\\.\SIWVID"]:
+        pass
+    elif fname.upper() in ['NUL']:
+        ret = winobjs.module_cur_hwnd
+    else:
+        # nuxify path
+        fname = fname.replace('\\', "/").lower()
+        # go in sandbox files
+        f = os.path.join('file_sb', fname)
+        if access & 0x80000000:
+            # read
+            if dwcreationdisposition == 2:
+                # create_always
+                if os.access(f, os.R_OK):
+                    # but file exist
+                    pass
+                else:
+                    raise NotImplementedError("Untested case")  # to test
+                    h = open(f, 'rb+')
+            elif dwcreationdisposition == 3:
+                # open_existing
+                if os.access(f, os.R_OK):
+                    s = os.stat(f)
+                    if stat.S_ISDIR(s.st_mode):
+                        ret = winobjs.handle_pool.add(f, 0x1337)
+                    else:
+                        h = open(f, 'rb+')
+                        ret = winobjs.handle_pool.add(f, h)
+                else:
+                    print "FILE %r DOES NOT EXIST!" % fname
+                    pass
+            elif dwcreationdisposition == 1:
+                # create new
+                if os.access(f, os.R_OK):
+                    # file exist
+                    # ret = 80
+                    winobjs.lastwin32error = 80
+                    pass
+                else:
+                    open(f, 'w')
+                    h = open(f, 'rb+')
+                    ret = winobjs.handle_pool.add(f, h)
+            else:
+                raise NotImplementedError("Untested case")
+        elif access & 0x40000000:
+            # write
+            if dwcreationdisposition == 3:
+                # open existing
+                if is_original_file:
+                    # cannot open self in write mode!
+                    pass
+                elif os.access(f, os.R_OK):
+                    s = os.stat(f)
+                    if stat.S_ISDIR(s.st_mode):
+                        # open dir
+                        ret = winobjs.handle_pool.add(f, 0x1337)
+                    else:
+                        h = open(f, 'rb+')
+                        ret = winobjs.handle_pool.add(f, h)
+                else:
+                    raise NotImplementedError("Untested case")  # to test
+            elif dwcreationdisposition == 5:
+                # truncate_existing
+                if is_original_file:
+                    pass
+                else:
+                    raise NotImplementedError("Untested case")  # to test
+            else:
+                # raise NotImplementedError("Untested case") # to test
+                h = open(f, 'w')
+                ret = winobjs.handle_pool.add(f, h)
+        else:
+            raise NotImplementedError("Untested case")
+
+        # h = open(f, 'rb+')
+        # ret = winobjs.handle_pool.add(f, h)
+    print 'ret', hex(ret)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_CreateFileA(myjit):
+    kernel32_CreateFile(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_CreateFileW(myjit):
+    kernel32_CreateFile(myjit, whoami(), lambda x, y: get_str_unic(myjit, y))
+
+
+def kernel32_ReadFile(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    (hwnd, lpbuffer, nnumberofbytestoread,
+     lpnumberofbytesread, lpoverlapped) = args
+
+    if hwnd == winobjs.module_cur_hwnd:
+        pass
+    elif hwnd in winobjs.handle_pool:
+        pass
+    else:
+        raise ValueError('unknown hwnd!')
+
+    eax = 0xffffffff
+    data = None
+    if hwnd in winobjs.files_hwnd:
+        data = winobjs.files_hwnd[
+            winobjs.module_cur_hwnd].read(nnumberofbytestoread)
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        data = wh.info.read(nnumberofbytestoread)
+    else:
+        raise ValueError('unknown filename')
+
+    if data is not None:
+        if (lpnumberofbytesread):
+            myjit.vm.vm_set_mem(lpnumberofbytesread, pck32(len(data)))
+        myjit.vm.vm_set_mem(lpbuffer, data)
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetFileSize(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    hwnd, lpfilesizehight = args
+
+    if hwnd == winobjs.module_cur_hwnd:
+        ret = len(open(winobjs.module_fname_nux).read())
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        print wh
+        ret = len(open(wh.name).read())
+    else:
+        raise ValueError('unknown hwnd!')
+
+    if lpfilesizehight != 0:
+        myjit.vm.vm_set_mem(lpfilesizehight, pck32(ret))
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetFileSizeEx(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    hwnd, lpfilesizehight = args
+
+    if hwnd == winobjs.module_cur_hwnd:
+        l = len(open(winobjs.module_fname_nux).read())
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        print wh
+        l = len(open(wh.name).read())
+    else:
+        raise ValueError('unknown hwnd!')
+
+    if lpfilesizehight == 0:
+        raise NotImplementedError("Untested case")
+    myjit.vm.vm_set_mem(lpfilesizehight, pck32(
+        l & 0xffffffff) + pck32((l >> 32) & 0xffffffff))
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_FlushInstructionCache(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    hprocess, lpbasead, dwsize = args
+    myjit.func_ret_stdcall(ret_ad, 0x1337)
+
+
+def kernel32_VirtualProtect(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    lpvoid, dwsize, flnewprotect, lpfloldprotect = args
+
+    # XXX mask hpart
+    flnewprotect &= 0xFFF
+
+    if not flnewprotect in access_dict:
+        raise ValueError('unknown access dw!')
+    myjit.vm.vm_set_mem_access(lpvoid, access_dict[flnewprotect])
+
+    # XXX todo real old protect
+    if lpfloldprotect:
+        myjit.vm.vm_set_mem(lpfloldprotect, pck32(0x40))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_VirtualAlloc(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    lpvoid, dwsize, alloc_type, flprotect = args
+
+    access_dict = {0x0: 0,
+                   0x1: 0,
+                   0x2: PAGE_READ,
+                   0x4: PAGE_READ | PAGE_WRITE,
+                   0x10: PAGE_EXEC,
+                   0x20: PAGE_EXEC | PAGE_READ,
+                   0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                   0x100: 0
+                       }
+
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+    if not flprotect in access_dict:
+        raise ValueError('unknown access dw!')
+
+    if lpvoid == 0:
+        alloc_addr = get_next_alloc_addr(dwsize)
+        myjit.vm.vm_add_memory_page(
+            alloc_addr, access_dict[flprotect], "\x00" * dwsize)
+    else:
+        all_mem = myjit.vm.vm_get_all_memory()
+        if lpvoid in all_mem:
+            alloc_addr = lpvoid
+            myjit.vm.vm_set_mem_access(lpvoid, access_dict[flprotect])
+        else:
+            alloc_addr = get_next_alloc_addr(dwsize)
+            # alloc_addr = lpvoid
+            myjit.vm.vm_add_memory_page(
+                alloc_addr, access_dict[flprotect], "\x00" * dwsize)
+
+    print 'Memory addr:', hex(alloc_addr)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_VirtualFree(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    lpvoid, dwsize, alloc_type = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def user32_GetWindowLongA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    hwnd, nindex = args
+    myjit.func_ret_stdcall(ret_ad, winobjs.windowlong_dw)
+
+
+def user32_SetWindowLongA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    hwnd, nindex, newlong = args
+    myjit.func_ret_stdcall(ret_ad, winobjs.windowlong_dw)
+
+
+def kernel32_GetModuleFileName(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    hmodule, lpfilename, nsize = args
+
+    if hmodule in [0, winobjs.hcurmodule]:
+        p = winobjs.module_path[:]
+    elif (winobjs.runtime_dll and
+        hmodule in winobjs.runtime_dll.name2off.values()):
+        name_inv = dict([(x[1], x[0])
+                        for x in winobjs.runtime_dll.name2off.items()])
+        p = name_inv[hmodule]
+    else:
+        print ValueError('unknown module h', hex(hmodule))
+        p = None
+
+    if p is None:
+        l = 0
+    elif nsize < len(p):
+        p = p[:nsize]
+        l = len(p)
+    else:
+        l = len(p)
+
+    print repr(p)
+    if p:
+        myjit.vm.vm_set_mem(lpfilename, set_str(p))
+
+    myjit.func_ret_stdcall(ret_ad, l)
+
+
+def kernel32_GetModuleFileNameA(myjit):
+    kernel32_GetModuleFileName(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetModuleFileNameW(myjit):
+    kernel32_GetModuleFileName(myjit, whoami(), set_str_unic)
+
+
+def kernel32_CreateMutex(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    print funcname
+    mutexattr, initowner, lpname = args
+
+    if lpname:
+        name = get_str(myjit, lpname)
+        print repr(name)
+    else:
+        name = None
+    if initowner:
+        if name in winobjs.mutex:
+            raise NotImplementedError("Untested case")
+            ret = 0
+        else:
+            winobjs.mutex[name] = id(name)
+            ret = winobjs.mutex[name]
+    else:
+        if name in winobjs.mutex:
+            raise NotImplementedError("Untested case")
+            ret = 0
+        else:
+            winobjs.mutex[name] = id(name)
+            ret = winobjs.mutex[name]
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_CreateMutexA(myjit):
+    kernel32_CreateMutex(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_CreateMutexW(myjit):
+    kernel32_CreateMutex(myjit, whoami(), get_str_unic)
+
+
+def shell32_SHGetSpecialFolderLocation(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    hwndowner, nfolder, ppidl = args
+    myjit.vm.vm_set_mem(ppidl, pck32(nfolder))
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_SHGetPathFromIDList(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    pidl, ppath = args
+
+    if pidl == 7:  # CSIDL_STARTUP:
+        s = "c:\\doc\\user\\startmenu\\programs\\startup"
+        s = set_str(s)
+    else:
+        raise ValueError('pidl not implemented', pidl)
+    myjit.vm.vm_set_mem(ppath, s)
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def shell32_SHGetPathFromIDListW(myjit):
+    kernel32_SHGetPathFromIDList(myjit, whoami(), set_str_unic)
+
+
+def shell32_SHGetPathFromIDListA(myjit):
+    kernel32_SHGetPathFromIDList(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetLastError(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, winobjs.lastwin32error)
+
+
+def kernel32_SetLastError(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    e, = args
+    # lasterr addr
+    # ad = seh_helper.FS_0_AD + 0x34
+    # myjit.vm.vm_set_mem(ad, pck32(e))
+    winobjs.lastwin32error = e
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_RestoreLastError(myjit):
+    kernel32_SetLastError(myjit)
+
+
+def kernel32_LoadLibraryA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    dllname, = args
+
+    libname = get_str_ansi(myjit, dllname, 0x100)
+    print repr(libname)
+
+    ret = winobjs.runtime_dll.lib_get_add_base(libname)
+    print "ret", hex(ret)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_LoadLibraryExA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    dllname, hfile, flags = args
+
+    if hfile != 0:
+        raise NotImplementedError("Untested case")
+    libname = get_str_ansi(myjit, dllname, 0x100)
+    print repr(libname)
+
+    ret = winobjs.runtime_dll.lib_get_add_base(libname)
+    print "ret", hex(ret)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetProcAddress(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    libbase, fname = args
+    fname = fname & 0xFFFFFFFF
+    if fname < 0x10000:
+        fname = fname
+    else:
+        fname = get_str_ansi(myjit, fname, 0x100)
+        if not fname:
+            fname = None
+    print repr(fname)
+    if fname is not None:
+        ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname)
+    else:
+        ad = 0
+    ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname)
+
+    myjit.func_ret_stdcall(ret_ad, ad)
+
+
+def kernel32_LoadLibraryW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    dllname, = args
+
+    libname = get_str_unic(myjit, dllname, 0x100)
+    print repr(libname)
+
+    ret = winobjs.runtime_dll.lib_get_add_base(libname)
+    print "ret", hex(ret)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetModuleHandle(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    dllname, = args
+
+    if dllname:
+        libname = get_str(myjit, dllname)
+        print repr(libname)
+        if libname:
+            ret = winobjs.runtime_dll.lib_get_add_base(libname)
+        else:
+            print 'unknown module!'
+            ret = 0
+    else:
+        ret = winobjs.current_pe.NThdr.ImageBase
+        print "default img base", hex(ret)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetModuleHandleA(myjit):
+    kernel32_GetModuleHandle(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_GetModuleHandleW(myjit):
+    kernel32_GetModuleHandle(myjit, whoami(), get_str_unic)
+
+
+def kernel32_VirtualLock(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    lpaddress, dwsize = args
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+class systeminfo:
+    oemId = 0
+    dwPageSize = 0x1000
+    lpMinimumApplicationAddress = 0x10000
+    lpMaximumApplicationAddress = 0x7ffeffff
+    dwActiveProcessorMask = 0x1
+    numberOfProcessors = 0x1
+    ProcessorsType = 586
+    dwAllocationgranularity = 0x10000
+    wProcessorLevel = 0x6
+    ProcessorRevision = 0xf0b
+
+    def pack(self):
+        return struct.pack('IIIIIIIIHH',
+                           self.oemId,
+                           self.dwPageSize,
+                           self.lpMinimumApplicationAddress,
+                           self.lpMaximumApplicationAddress,
+                           self.dwActiveProcessorMask,
+                           self.numberOfProcessors,
+                           self.ProcessorsType,
+                           self.dwAllocationgranularity,
+                           self.wProcessorLevel,
+                           self.ProcessorRevision)
+
+
+def kernel32_GetSystemInfo(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    sys_ptr, = args
+    sysinfo = systeminfo()
+    myjit.vm.vm_set_mem(sys_ptr, sysinfo.pack())
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_IsWow64Process(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    h, bool_ptr = args
+
+    myjit.vm.vm_set_mem(bool_ptr, pck32(0))
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetCommandLineA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    s = winobjs.module_path + '\x00'
+    s = '"%s"' % s
+    alloc_addr = alloc_mem(myjit, 0x1000)
+    myjit.vm.vm_set_mem(alloc_addr, s)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_GetCommandLineW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    s = winobjs.module_path + '\x00'
+    s = set_str_unic('"%s"' % s)
+    alloc_addr = alloc_mem(myjit, 0x1000)
+    myjit.vm.vm_set_mem(alloc_addr, s)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def shell32_CommandLineToArgvW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    pcmd, pnumargs = args
+    cmd = get_str_unic(myjit, pcmd)
+    print repr(cmd)
+    tks = cmd.split(' ')
+    addr = alloc_mem(myjit, len(cmd) * 2 + 4 * len(tks))
+    addr_ret = alloc_mem(myjit, 4 * (len(tks) + 1))
+    o = 0
+    for i, t in enumerate(tks):
+        x = set_str_unic(t) + "\x00\x00"
+        myjit.vm.vm_set_mem(addr_ret + 4 * i, pck32(addr + o))
+        myjit.vm.vm_set_mem(addr + o, x)
+        o += len(x) + 2
+
+    myjit.vm.vm_set_mem(addr_ret + 4 * i, pck32(0))
+    myjit.vm.vm_set_mem(pnumargs, pck32(len(tks)))
+    myjit.func_ret_stdcall(ret_ad, addr_ret)
+
+
+def cryptdll_MD5Init(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ad_ctx, = args
+    index = len(winobjs.cryptdll_md5_h)
+    h = MD5.new()
+    winobjs.cryptdll_md5_h[index] = h
+
+    myjit.vm.vm_set_mem(ad_ctx, pck32(index))
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def cryptdll_MD5Update(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ad_ctx, ad_input, inlen = args
+
+    index = myjit.vm.vm_get_mem(ad_ctx, 4)
+    index = upck32(index)
+    if not index in winobjs.cryptdll_md5_h:
+        raise ValueError('unknown h context', index)
+
+    data = myjit.vm.vm_get_mem(ad_input, inlen)
+    winobjs.cryptdll_md5_h[index].update(data)
+    print hexdump(data)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def cryptdll_MD5Final(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ad_ctx, = args
+
+    index = myjit.vm.vm_get_mem(ad_ctx, 4)
+    index = upck32(index)
+    if not index in winobjs.cryptdll_md5_h:
+        raise ValueError('unknown h context', index)
+    h = winobjs.cryptdll_md5_h[index].digest()
+    myjit.vm.vm_set_mem(ad_ctx + 88, h)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlInitAnsiString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    ad_ctx, ad_str = args
+
+    s = get_str_ansi(myjit, ad_str)
+    l = len(s)
+    print "string", l, s
+    myjit.vm.vm_set_mem(ad_ctx, pw(l) + pw(l + 1) + pck32(ad_str))
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlHashUnicodeString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    ad_ctxu, case_i, h_id, phout = args
+
+    print hex(h_id)
+    if h_id != 1:
+        raise ValueError('unk hash unicode', h_id)
+
+    l1, l2, ptra = struct.unpack('HHL', myjit.vm.vm_get_mem(ad_ctxu, 8))
+    print hex(l1), hex(l2), hex(ptra)
+    s = myjit.vm.vm_get_mem(ptra, l1)
+    print repr(s)
+    s = s[:-1]
+    print repr(s)
+    hv = 0
+
+    if case_i:
+        s = s.lower()
+    for c in s:
+        hv = ((65599 * hv) + ord(c)) & 0xffffffff
+    print "unicode h", hex(hv)
+    myjit.vm.vm_set_mem(phout, pck32(hv))
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_RtlMoveMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ad_dst, ad_src, m_len = args
+    data = myjit.vm.vm_get_mem(ad_src, m_len)
+    myjit.vm.vm_set_mem(ad_dst, data)
+    print hexdump(data)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlAnsiCharToUnicodeChar(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ad_ad_ch, = args
+    ad_ch = upck32(myjit.vm.vm_get_mem(ad_ad_ch, 4))
+    print hex(ad_ch)
+    ch = ord(myjit.vm.vm_get_mem(ad_ch, 1))
+    myjit.vm.vm_set_mem(ad_ad_ch, pck32(ad_ch + 1))
+
+    print repr(ch), repr(chr(ch))
+    myjit.func_ret_stdcall(ret_ad, ch)
+
+
+def ntdll_RtlFindCharInUnicodeString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    flags, main_str_ad, search_chars_ad, pos_ad = args
+
+    print flags
+    if flags != 0:
+        raise ValueError('unk flags')
+
+    ml1, ml2, mptra = struct.unpack('HHL', myjit.vm.vm_get_mem(main_str_ad, 8))
+    print ml1, ml2, hex(mptra)
+    sl1, sl2, sptra = struct.unpack(
+        'HHL', myjit.vm.vm_get_mem(search_chars_ad, 8))
+    print sl1, sl2, hex(sptra)
+    main_data = myjit.vm.vm_get_mem(mptra, ml1)[:-1]
+    search_data = myjit.vm.vm_get_mem(sptra, sl1)[:-1]
+
+    print repr(main_data)
+    print repr(search_data)
+
+    pos = None
+    for i, c in enumerate(main_data):
+        for s in search_data:
+            if s == c:
+                pos = i
+                break
+        if pos:
+            break
+    print pos
+    if pos is None:
+        ret = 0xC0000225
+        myjit.vm.vm_set_mem(pos_ad, pck32(0))
+    else:
+        ret = 0
+        myjit.vm.vm_set_mem(pos_ad, pck32(pos))
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def ntdll_RtlComputeCrc32(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    dwinit, pdata, ilen = args
+
+    data = myjit.vm.vm_get_mem(pdata, ilen)
+    print hex(dwinit)
+    print hexdump(data)
+    crc_r = crc32(data, dwinit)
+    print "crc32", hex(crc_r)
+    myjit.func_ret_stdcall(ret_ad, crc_r)
+
+
+def ntdll_RtlExtendedIntegerMultiply(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    b2, b1, bm = args
+    a = (b1 << 32) + b2
+    a = a * bm
+    print hex(a)
+    myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
+
+
+def ntdll_RtlLargeIntegerAdd(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    a2, a1, b2, b1 = args
+    a = (a1 << 32) + a2 + (b1 << 32) + b2
+    print hex(a)
+    myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
+
+
+def ntdll_RtlLargeIntegerShiftRight(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    a2, a1, m = args
+    a = ((a1 << 32) + a2) >> m
+    print hex(a)
+    myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
+
+
+def ntdll_RtlEnlargedUnsignedMultiply(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    a, b = args
+    a = a * b
+    print hex(a)
+    myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
+
+
+def ntdll_RtlLargeIntegerSubtract(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    a2, a1, b2, b1 = args
+    a = (a1 << 32) + a2 - (b1 << 32) + b2
+    print hex(a)
+    myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
+
+
+def ntdll_RtlCompareMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ad1, ad2, m_len = args
+    data1 = myjit.vm.vm_get_mem(ad1, m_len)
+    data2 = myjit.vm.vm_get_mem(ad2, m_len)
+
+    print hexdump(data1)
+    print hexdump(data2)
+    i = 0
+    while data1[i] == data2[i]:
+        i += 1
+        if i >= m_len:
+            break
+
+    myjit.func_ret_stdcall(ret_ad, i)
+
+
+def user32_GetMessagePos(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0x00110022)
+
+
+def kernel32_Sleep(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    t, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_ZwUnmapViewOfSection(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    h, ad = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_IsBadReadPtr(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    lp, ucb = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_KeInitializeEvent(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    my_event, my_type, my_state = args
+    myjit.vm.vm_set_mem(my_event, pck32(winobjs.win_event_num))
+    winobjs.win_event_num += 1
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_RtlGetVersion(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ptr_version, = args
+
+    s = struct.pack("IIIII",
+                    0x114,  # struct size
+                    0x5,   # maj vers
+                    0x2,  # min vers
+                    0x666,  # build nbr
+                    0x2,   # platform id
+                    ) + set_str_unic("Service pack 4")
+
+    myjit.vm.vm_set_mem(ptr_version, s)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_RtlVerifyVersionInfo(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ptr_version, = args
+
+    s = myjit.vm.vm_get_mem(ptr_version, 0x5 * 4)
+    print repr(s)
+    s_size, s_majv, s_minv, s_buildn, s_platform = struct.unpack('IIIII', s)
+    print s_size, s_majv, s_minv, s_buildn, s_platform
+    raise NotImplementedError("Untested case")
+    myjit.vm.vm_set_mem(ptr_version, s)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def hal_ExAcquireFastMutex(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def mdl2ad(n):
+    return winobjs.nt_mdl_ad + 0x10 * n
+
+
+def ad2mdl(ad):
+    return ((ad - winobjs.nt_mdl_ad) & 0xFFFFFFFFL) / 0x10
+
+
+def ntoskrnl_IoAllocateMdl(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    v_addr, l, second_buf, chargequota, pirp = args
+    m = mdl(v_addr, l)
+    winobjs.nt_mdl[winobjs.nt_mdl_cur] = m
+    myjit.vm.vm_set_mem(mdl2ad(winobjs.nt_mdl_cur), str(m))
+    myjit.func_ret_stdcall(ret_ad, mdl2ad(winobjs.nt_mdl_cur))
+    winobjs.nt_mdl_cur += 1
+
+
+def ntoskrnl_MmProbeAndLockPages(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    p_mdl, access_mode, op = args
+
+    if not ad2mdl(p_mdl) in winobjs.nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_MmMapLockedPagesSpecifyCache(myjit):
+    ret_ad, args = myjit.func_args_stdcall(6)
+    p_mdl, access_mode, cache_type, base_ad, bugcheckonfailure, priority = args
+    if not ad2mdl(p_mdl) in winobjs.nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    myjit.func_ret_stdcall(ret_ad, winobjs.nt_mdl[ad2mdl(p_mdl)].ad)
+
+
+def ntoskrnl_MmProtectMdlSystemAddress(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    p_mdl, prot = args
+    if not ad2mdl(p_mdl) in winobjs.nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_MmUnlockPages(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    p_mdl, = args
+    if not ad2mdl(p_mdl) in winobjs.nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_IoFreeMdl(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    p_mdl, = args
+    if not ad2mdl(p_mdl) in winobjs.nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+    del(winobjs.nt_mdl[ad2mdl(p_mdl)])
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def hal_ExReleaseFastMutex(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_RtlQueryRegistryValues(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    relativeto, path, querytable, context, environ = args
+    p = get_str_unic(myjit, path)
+    print repr(p)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntoskrnl_ExAllocatePoolWithTagPriority(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    pool_type, nbr_of_bytes, tag, priority = args
+
+    alloc_addr = get_next_alloc_addr(nbr_of_bytes)
+    myjit.vm.vm_add_memory_page(
+        alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * nbr_of_bytes)
+
+    print "ad", hex(alloc_addr)
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def my_lstrcmp(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    ptr_str1, ptr_str2 = args
+    s1 = get_str(ptr_str1)
+    s2 = get_str(ptr_str2)
+    print '%s (%r, %r)' % (' ' * len(funcname), s1, s2)
+    myjit.func_ret_stdcall(ret_ad, cmp(s1, s2))
+
+
+def kernel32_lstrcmpA(myjit):
+    my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x))
+
+
+def kernel32_lstrcmpiA(myjit):
+    my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x).lower())
+
+
+def kernel32_lstrcmpW(myjit):
+    my_lstrcmp(myjit, whoami(), lambda x: get_str_unic(myjit, x))
+
+
+def kernel32_lstrcmpiW(myjit):
+    my_lstrcmp(myjit, whoami(), lambda x: get_str_unic(myjit, x).lower())
+
+
+def kernel32_lstrcmpi(myjit):
+    my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x).lower())
+
+
+def my_strcpy(myjit, funcname, get_str, set_str):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    ptr_str1, ptr_str2 = args
+    s2 = get_str(myjit, ptr_str2)
+    print '%s (%r)' % (funcname, s2)
+    myjit.vm.vm_set_mem(ptr_str1, set_str(s2))
+    myjit.func_ret_stdcall(ret_ad, ptr_str1)
+
+
+def kernel32_lstrcpyW(myjit):
+    my_strcpy(myjit, whoami(), get_str_unic,
+              lambda x: set_str_unic(x) + "\x00\x00")
+
+
+def kernel32_lstrcpyA(myjit):
+    my_strcpy(myjit, whoami(), get_str_ansi, lambda x: x + "\x00")
+
+
+def kernel32_lstrcpy(myjit):
+    my_strcpy(myjit, whoami(), get_str_ansi, lambda x: x + "\x00")
+
+
+def kernel32_lstrcpyn(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ptr_str1, ptr_str2, mlen = args
+    s2 = get_str_ansi(myjit, ptr_str2)
+    print repr(s2)
+    s2 = s2[:mlen]
+    myjit.vm.vm_set_mem(ptr_str1, s2)
+
+    myjit.func_ret_stdcall(ret_ad, ptr_str1)
+
+
+def my_strlen(myjit, funcname, get_str, mylen):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    arg_src, = args
+    src = get_str(myjit, arg_src)
+    print funcname, repr(src)
+    myjit.func_ret_stdcall(ret_ad, mylen(src))
+
+
+def kernel32_lstrlenA(myjit):
+    my_strlen(myjit, whoami(), get_str_ansi, lambda x: len(x))
+
+
+def kernel32_lstrlenW(myjit):
+    my_strlen(myjit, whoami(), get_str_unic, lambda x: len(x))
+
+
+def kernel32_lstrlen(myjit):
+    my_strlen(myjit, whoami(), get_str_ansi, lambda x: len(x))
+
+
+def my_lstrcat(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ptr_str1, ptr_str2 = args
+    s1 = get_str(myjit, ptr_str1)
+    s2 = get_str(myjit, ptr_str2)
+    print '%s (%r, %r)' % (whoami(), s1, s2)
+
+    s = s1 + s2
+    print repr(s)
+    myjit.vm.vm_set_mem(ptr_str1, s1 + s2)
+    myjit.func_ret_stdcall(ret_ad, ptr_str1)
+
+
+def kernel32_lstrcatA(myjit):
+    my_lstrcat(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_lstrcatW(myjit):
+    my_lstrcat(myjit, whoami(), get_str_unic)
+
+
+def kernel32_GetUserGeoID(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    geoclass, = args
+    if geoclass == 14:
+        ret = 12345678
+    elif geoclass == 16:
+        ret = 55667788
+    else:
+        raise ValueError('unknown geolcass')
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def my_GetVolumeInformation(myjit, funcname, get_str, set_str):
+    ret_ad, args = myjit.func_args_stdcall(8)
+    (lprootpathname, lpvolumenamebuffer, nvolumenamesize,
+     lpvolumeserialnumber, lpmaximumcomponentlength, lpfilesystemflags,
+     lpfilesystemnamebuffer, nfilesystemnamesize) = args
+
+    print funcname, hex(lprootpathname), hex(lpvolumenamebuffer), \
+        hex(nvolumenamesize), hex(lpvolumeserialnumber), \
+        hex(lpmaximumcomponentlength), hex(lpfilesystemflags), \
+        hex(lpfilesystemnamebuffer), hex(nfilesystemnamesize)
+
+    if lprootpathname:
+        s = get_str(myjit, lprootpathname)
+        print repr(s)
+
+    if lpvolumenamebuffer:
+        s = "volumename"
+        s = s[:nvolumenamesize]
+        myjit.vm.vm_set_mem(lpvolumenamebuffer, set_str(s))
+
+    if lpvolumeserialnumber:
+        myjit.vm.vm_set_mem(lpvolumeserialnumber, pck32(11111111))
+    if lpmaximumcomponentlength:
+        myjit.vm.vm_set_mem(lpmaximumcomponentlength, pck32(0xff))
+    if lpfilesystemflags:
+        myjit.vm.vm_set_mem(lpfilesystemflags, pck32(22222222))
+
+    if lpfilesystemnamebuffer:
+        s = "filesystemname"
+        s = s[:nfilesystemnamesize]
+        myjit.vm.vm_set_mem(lpfilesystemnamebuffer, set_str(s))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetVolumeInformationA(myjit):
+    my_GetVolumeInformation(
+        myjit, whoami(), get_str_ansi, lambda x: x + "\x00")
+
+
+def kernel32_GetVolumeInformationW(myjit):
+    my_GetVolumeInformation(myjit, whoami(), get_str_unic, set_str_unic)
+
+
+def kernel32_MultiByteToWideChar(myjit):
+    ret_ad, args = myjit.func_args_stdcall(6)
+    (codepage, dwflags, lpmultibytestr,
+     cbmultibyte, lpwidecharstr, cchwidechar) = args
+
+    print whoami(), hex(ret_ad), \
+        hex(codepage), hex(dwflags), hex(lpmultibytestr), hex(
+            cbmultibyte), hex(lpwidecharstr), hex(cchwidechar)
+    src = get_str_ansi(myjit, lpmultibytestr) + '\x00'
+    l = len(src)
+    print repr(src)
+
+    src = "\x00".join(list(src))
+    print repr(src), hex(len(src))
+    myjit.vm.vm_set_mem(lpwidecharstr, src)
+    myjit.func_ret_stdcall(ret_ad, l)
+
+
+def my_GetEnvironmentVariable(myjit, funcname, get_str, set_str, mylen):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    lpname, lpbuffer, nsize = args
+
+    s = get_str(myjit, lpname)
+    if get_str == get_str_unic:
+        s = s
+    print 'variable', repr(s)
+    if s in winobjs.env_variables:
+        v = set_str(winobjs.env_variables[s])
+    else:
+        print 'WARNING unknown env variable', repr(s)
+        v = ""
+    print 'return', repr(v)
+    myjit.vm.vm_set_mem(lpbuffer, v)
+    myjit.func_ret_stdcall(ret_ad, mylen(v))
+
+
+def my_GetSystemDirectory(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    lpbuffer, usize = args
+    print funcname
+
+    s = "c:\\windows\\system32"
+    l = len(s)
+    s = set_str(s)
+    myjit.vm.vm_set_mem(lpbuffer, s)
+
+    myjit.func_ret_stdcall(ret_ad, l)
+
+
+def kernel32_GetSystemDirectoryA(myjit):
+    my_GetSystemDirectory(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetSystemDirectoryW(myjit):
+    my_GetSystemDirectory(myjit, whoami(), set_str_unic)
+
+
+def my_CreateDirectory(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    lppath, secattrib = args
+    p = get_str(myjit, lppath)
+    myjit.func_ret_stdcall(ret_ad, 0x1337)
+
+
+def kernel32_CreateDirectoryW(myjit):
+    my_CreateDirectory(myjit, whoami(), get_str_unic)
+
+
+def kernel32_CreateDirectoryA(myjit):
+    my_CreateDirectory(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_GetEnvironmentVariableA(myjit):
+    my_GetEnvironmentVariable(myjit, whoami(),
+                              get_str_ansi,
+                              lambda x: x + "\x00",
+                              lambda x: len(x))
+
+
+def kernel32_GetEnvironmentVariableW(myjit):
+    my_GetEnvironmentVariable(myjit, whoami(),
+                              get_str_unic,
+                              lambda x: "\x00".join(list(x + "\x00")),
+                              lambda x: len(x))
+
+
+def my_CreateEvent(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    lpeventattributes, bmanualreset, binitialstate, lpname = args
+    if lpname:
+        s = get_str(myjit, lpname)
+    else:
+        s = None
+    print repr(s)
+    if not s in winobjs.events_pool:
+        winobjs.events_pool[s] = (bmanualreset, binitialstate)
+    else:
+        print 'WARNING: known event'
+
+    myjit.func_ret_stdcall(ret_ad, id(s))
+
+
+def kernel32_CreateEventA(myjit):
+    my_CreateEvent(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_CreateEventW(myjit):
+    my_CreateEvent(myjit, whoami(), get_str_unic)
+
+
+def kernel32_WaitForSingleObject(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    handle, dwms = args
+
+    print whoami(), hex(ret_ad), hex(handle), hex(dwms)
+
+    t_start = time.time() * 1000
+    found = False
+    while True:
+        if dwms and dwms + t_start > time.time() * 1000:
+            ret = 0x102
+            break
+        for k, v in winobjs.events_pool.items():
+            if k != handle:
+                continue
+            found = True
+            if winobjs.events_pool[k][1] == 1:
+                ret = 0
+                break
+        if not found:
+            print 'unknown handle'
+            ret = 0xffffffff
+            break
+        time.sleep(0.1)
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_SetFileAttributesA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    lpfilename, dwfileattributes = args
+    print whoami(), hex(ret_ad), hex(lpfilename), hex(dwfileattributes)
+
+    if lpfilename:
+        fname = get_str_ansi(myjit, lpfilename)
+        print "filename", repr(fname)
+        ret = 1
+    else:
+        ret = 0
+        myjit.vm.vm_set_mem(seh_helper.FS_0_AD + 0x34, pck32(3))
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def ntdll_RtlMoveMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    dst, src, l = args
+    s = myjit.vm.vm_get_mem(src, l)
+    myjit.vm.vm_set_mem(dst, s)
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def ntdll_ZwQuerySystemInformation(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    (systeminformationclass, systeminformation,
+     systeminformationl, returnl) = args
+    if systeminformationclass == 2:
+        # SYSTEM_PERFORMANCE_INFORMATION
+        o = struct.pack('II', 0x22222222, 0x33333333)
+        o += "\x00" * systeminformationl
+        o = o[:systeminformationl]
+        myjit.vm.vm_set_mem(systeminformation, o)
+    else:
+        raise ValueError('unknown sysinfo class', systeminformationclass)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_ZwProtectVirtualMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    handle, lppvoid, pdwsize, flnewprotect, lpfloldprotect = args
+
+    ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4))
+    dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4))
+    print 'ad', hex(ad), 'size', hex(dwsize)
+    # XXX mask hpart
+    flnewprotect &= 0xFFF
+
+    if not flnewprotect in access_dict:
+        raise ValueError('unknown access dw!')
+    myjit.vm.vm_set_mem_access(ad, access_dict[flnewprotect])
+
+    # XXX todo real old protect
+    myjit.vm.vm_set_mem(lpfloldprotect, pck32(0x40))
+
+    dump_memory_page_pool_py()
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def ntdll_ZwAllocateVirtualMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(6)
+    handle, lppvoid, zerobits, pdwsize, alloc_type, flprotect = args
+
+    ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4))
+    dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4))
+    print 'ad', hex(ad), 'size', hex(dwsize)
+
+    access_dict = {0x0: 0,
+                   0x1: 0,
+                   0x2: PAGE_READ,
+                   0x4: PAGE_READ | PAGE_WRITE,
+                   0x10: PAGE_EXEC,
+                   0x20: PAGE_EXEC | PAGE_READ,
+                   0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                   0x100: 0
+                       }
+
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+    if not flprotect in access_dict:
+        raise ValueError('unknown access dw!')
+
+    alloc_addr = get_next_alloc_addr(dwsize)
+    myjit.vm.vm_add_memory_page(
+        alloc_addr, access_dict[flprotect], "\x00" * dwsize)
+    myjit.vm.vm_set_mem(lppvoid, pck32(alloc_addr))
+
+    print 'ret', hex(alloc_addr)
+    dump_memory_page_pool_py()
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_ZwFreeVirtualMemory(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    handle, lppvoid, pdwsize, alloc_type = args
+    ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4))
+    dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4))
+    print 'ad', hex(ad), 'size', hex(dwsize)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlInitString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    pstring, source = args
+    s = get_str_ansi(myjit, source)
+    print "str", repr(s)
+
+    l = len(s) + 1
+
+    o = struct.pack('HHI', l, l, source)
+    myjit.vm.vm_set_mem(pstring, o)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlAnsiStringToUnicodeString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    dst, src, alloc_str = args
+
+    l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(src, 0x8))
+    print hex(l1), hex(l2), hex(p_src)
+    s = get_str_ansi(myjit, p_src)
+    print "str", repr(s)
+    s = ("\x00".join(s + "\x00"))
+    l = len(s) + 1
+    if alloc_str:
+        print 'alloc'
+        alloc_addr = get_next_alloc_addr(l)
+        myjit.vm.vm_add_memory_page(
+            alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * l)
+    else:
+        print 'use buf'
+        alloc_addr = p_src
+    myjit.vm.vm_set_mem(alloc_addr, s)
+    o = struct.pack('HHI', l, l, alloc_addr)
+    myjit.vm.vm_set_mem(dst, o)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_LdrLoadDll(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    path, flags, modname, modhandle = args
+
+    print whoami(), hex(ret_ad),
+    print '(', hex(path), hex(flags), hex(modname), hex(modhandle), ')'
+    l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(modname, 0x8))
+    print hex(l1), hex(l2), hex(p_src)
+    s = get_str_unic(myjit, p_src)
+    print repr(s)
+    libname = s.lower()
+    print repr(libname)
+
+    ad = winobjs.runtime_dll.lib_get_add_base(libname)
+    print "ret", hex(ad)
+    myjit.vm.vm_set_mem(modhandle, pck32(ad))
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_RtlFreeUnicodeString(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    src, = args
+
+    l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(src, 0x8))
+    print hex(l1), hex(l2), hex(p_src)
+    s = get_str_unic(myjit, p_src)
+    print "str", repr(s)
+    print repr(s)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_LdrGetProcedureAddress(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    libbase, pfname, opt, p_ad = args
+
+    l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(pfname, 0x8))
+    print hex(l1), hex(l2), hex(p_src)
+    fname = get_str_ansi(myjit, p_src)
+    print "str", repr(fname)
+
+    ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname)
+
+    myjit.vm.vm_set_mem(p_ad, pck32(ad))
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def ntdll_memset(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    arg_addr, arg_c, arg_size = args
+
+    myjit.vm.vm_set_mem(arg_addr, chr(arg_c) * arg_size)
+    myjit.func_ret_stdcall(ret_ad, arg_addr)
+
+
+def msvcrt_memset(myjit):
+    ret_ad, args = myjit.func_args_cdecl(3)
+    arg_addr, arg_c, arg_size = args
+
+    myjit.vm.vm_set_mem(arg_addr, chr(arg_c) * arg_size)
+    myjit.func_ret_cdecl(ret_ad, arg_addr)
+
+
+def msvcrt_memcpy(myjit):
+    ret_ad, args = myjit.func_args_cdecl(3)
+    dst, src, size = args
+
+    s = myjit.vm.vm_get_mem(src, size)
+    myjit.vm.vm_set_mem(dst, s)
+    myjit.func_ret_cdecl(ret_ad, dst)
+
+
+def msvcrt_memcmp(myjit):
+    ret_ad, args = myjit.func_args_cdecl(3)
+    ps1, ps2, size = args
+
+    s1 = myjit.vm.vm_get_mem(ps1, size)
+    s2 = myjit.vm.vm_get_mem(ps2, size)
+    ret = cmp(s1, s2)
+    myjit.func_ret_cdecl(ret_ad, ret)
+
+
+def shlwapi_PathFindExtensionA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    path_ad, = args
+
+    path = get_str_ansi(myjit, path_ad)
+    print repr(path)
+    i = path.rfind('.')
+    if i == -1:
+        i = path_ad + len(path)
+    else:
+        i = path_ad + i
+    myjit.func_ret_stdcall(ret_ad, i)
+
+
+def shlwapi_PathRemoveFileSpecW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    path_ad, = args
+
+    path = get_str_unic(myjit, path_ad)
+    print repr(path)
+    i = path.rfind('\\')
+    if i == -1:
+        i = 0
+    myjit.vm.vm_set_mem(path_ad + i * 2, "\x00\x00")
+    path = get_str_unic(myjit, path_ad)
+    print repr(path)
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def shlwapi_PathIsPrefixW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    ptr_prefix, ptr_path = args
+    prefix = get_str_unic(myjit, ptr_prefix)
+    path = get_str_unic(myjit, ptr_path)
+    print repr(prefix), repr(path)
+
+    if path.startswith(prefix):
+        ret = 1
+    else:
+        ret = 0
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def shlwapi_PathIsDirectoryW(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ppath, = args
+    fname = get_str_unic(myjit, ppath)
+
+    fname = fname.replace('\\', "/").lower()
+    f = os.path.join('file_sb', fname)
+
+    s = os.stat(f)
+    ret = 0
+    if stat.S_ISDIR(s.st_mode):
+        ret = 1
+
+    myjit.func_ret_cdecl(ret_ad, ret)
+
+
+def shlwapi_PathIsFileSpec(funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    path_ad, = args
+    path = get_str(myjit, path_ad)
+    print repr(path)
+    if path.find(':') != -1 and path.find('\\') != -1:
+        ret = 0
+    else:
+        ret = 1
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def shlwapi_PathGetDriveNumber(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    path_ad, = args
+    path = get_str(myjit, path_ad)
+    print repr(path)
+    l = ord(path[0].upper()) - ord('A')
+    if 0 <= l <= 25:
+        ret = l
+    else:
+        ret = -1
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def shlwapi_PathGetDriveNumberA(myjit):
+    shlwapi_PathGetDriveNumber(myjit, whoami(), get_str_ansi)
+
+
+def shlwapi_PathGetDriveNumberW(myjit):
+    shlwapi_PathGetDriveNumber(myjit, whoami(), get_str_unic)
+
+
+def shlwapi_PathIsFileSpecA(myjit):
+    shlwapi_PathIsFileSpec(whoami(), get_str_ansi)
+
+
+def shlwapi_PathIsFileSpecW(myjit):
+    shlwapi_PathIsFileSpec(whoami(), get_str_unic)
+
+
+def shlwapi_StrToIntA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    i_str_ad, = args
+    i_str = get_str_ansi(myjit, i_str_ad)
+    print repr(i_str)
+    try:
+        i = int(i_str)
+    except:
+        print 'WARNING cannot convert int'
+        i = 0
+
+    myjit.func_ret_stdcall(ret_ad, i)
+
+
+def shlwapi_StrToInt64Ex(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    pstr, flags, pret = args
+    i_str = get_str(myjit, pstr)
+    if get_str is get_str_unic:
+        i_str = i_str
+    print repr(i_str)
+
+    if flags == 0:
+        r = int(i_str)
+    elif flags == 1:
+        r = int(i_str, 16)
+    else:
+        raise ValueError('cannot decode int')
+
+    myjit.vm.vm_set_mem(pret, struct.pack('q', r))
+
+    myjit.func_ret_stdcall(ret_ad, i)
+
+
+def shlwapi_StrToInt64ExA(myjit):
+    shlwapi_StrToInt64Ex(myjit, whoami(), get_str_ansi)
+
+
+def shlwapi_StrToInt64ExW(myjit):
+    shlwapi_StrToInt64Ex(myjit, whoami(), get_str_unic)
+
+
+def user32_IsCharAlpha(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    c, = args
+    try:
+        c = chr(c)
+    except:
+        print 'bad char', c
+        c = "\x00"
+    if c.isalpha(myjit):
+        ret = 1
+    else:
+        ret = 0
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def user32_IsCharAlphaA(myjit):
+    user32_IsCharAlpha(myjit, whoami(), get_str_ansi)
+
+
+def user32_IsCharAlphaW(myjit):
+    user32_IsCharAlpha(myjit, whoami(), get_str_unic)
+
+
+def user32_IsCharAlphaNumericA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    c, = args
+    c = chr(c)
+    if c.isalnum(myjit):
+        ret = 1
+    else:
+        ret = 0
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def shlwapi_StrCmpNIA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ptr_str1, ptr_str2, nchar = args
+    s1 = get_str_ansi(myjit, ptr_str1).lower()
+    s2 = get_str_ansi(myjit, ptr_str2).lower()
+    s1 = s1[:nchar]
+    s2 = s2[:nchar]
+
+    print repr(s1), repr(s2)
+    myjit.func_ret_stdcall(ret_ad, cmp(s1, s2))
+
+
+def advapi32_RegOpenKeyEx(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hkey, subkey, reserved, access, phandle = args
+    if subkey:
+        s_subkey = get_str(myjit, subkey).lower()
+    else:
+        s_subkey = ""
+    print hex(hkey)
+    print repr(s_subkey)
+    print winobjs.hkey_handles
+
+    ret_hkey = 0
+    ret = 2
+    if hkey in winobjs.hkey_handles:
+        if s_subkey:
+            h = hash(s_subkey) & 0xffffffff
+            print hex(h)
+            if h in winobjs.hkey_handles:
+                ret_hkey = h
+                ret = 0
+        else:
+            print 'unknown skey'
+
+    print 'set hkey', hex(ret_hkey)
+    myjit.vm.vm_set_mem(phandle, pck32(ret_hkey))
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def advapi32_RegOpenKeyExA(myjit):
+    advapi32_RegOpenKeyEx(myjit, whoami(), get_str_ansi)
+
+
+def advapi32_RegOpenKeyExW(myjit):
+    advapi32_RegOpenKeyEx(myjit, whoami(), get_str_unic)
+
+
+def advapi32_RegSetValue(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hkey, psubkey, valuetype, pvalue, length = args
+    if psubkey:
+        subkey = get_str(myjit, psubkey).lower()
+    else:
+        subkey = ""
+    print repr(subkey)
+
+    if pvalue:
+        value = myjit.vm.vm_get_mem(pvalue, length)
+    else:
+        value = None
+    print repr(value)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def advapi32_RegSetValueA(myjit):
+    advapi32_RegSetValue(myjit, whoami(), get_str_ansi)
+
+
+def advapi32_RegSetValueW(myjit):
+    advapi32_RegSetValue(myjit, whoami(), get_str_unic)
+
+
+def kernel32_GetThreadLocale(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0x40c)
+
+
+def kernel32_GetLocaleInfo(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    localeid, lctype, lplcdata, cchdata = args
+
+    buf = None
+    ret = 0
+    if localeid == 0x40c:
+        if lctype == 0x3:
+            buf = "ENGLISH"
+            buf = buf[:cchdata - 1]
+            print 'SET', buf
+            myjit.vm.vm_set_mem(lplcdata, set_str(buf))
+            ret = len(buf)
+    else:
+        raise ValueError('unimpl localeid')
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetLocaleInfoA(myjit):
+    kernel32_GetLocaleInfo(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetLocaleInfoW(myjit):
+    kernel32_GetLocaleInfo(myjit, whoami(), set_str_unic)
+
+
+def kernel32_TlsAlloc(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    winobjs.tls_index += 1
+    myjit.func_ret_stdcall(ret_ad, winobjs.tls_index)
+
+
+def kernel32_TlsFree(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_TlsSetValue(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    tlsindex, tlsvalue = args
+    winobjs.tls_values[tlsindex] = tlsvalue
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_TlsGetValue(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    tlsindex, = args
+
+    print whoami(), hex(tlsindex)
+
+    if not tlsindex in winobjs.tls_values:
+        raise ValueError("unknown tls val", repr(tlsindex))
+    myjit.func_ret_stdcall(ret_ad, winobjs.tls_values[tlsindex])
+
+
+def user32_GetKeyboardType(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    typeflag, = args
+
+    ret = 0
+    if typeflag == 0:
+        ret = 4
+    else:
+        raise ValueError('unimpl keyboard type')
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetStartupInfo(myjit, funcname, set_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ptr, = args
+
+    print funcname, hex(ptr)
+
+    s = "\x00" * 0x2c + "\x81\x00\x00\x00" + "\x0a"
+
+    myjit.vm.vm_set_mem(ptr, s)
+    myjit.func_ret_stdcall(ret_ad, ptr)
+
+
+def kernel32_GetStartupInfoA(myjit):
+    kernel32_GetStartupInfo(myjit, whoami(), set_str_ansi)
+
+
+def kernel32_GetStartupInfoW(myjit):
+    kernel32_GetStartupInfo(myjit, whoami(), set_str_unic)
+
+
+def kernel32_GetCurrentThreadId(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0x113377)
+
+
+def kernel32_InitializeCriticalSection(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    lpcritic, = args
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def user32_GetSystemMetrics(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    nindex, = args
+
+    ret = 0
+    if nindex in [0x2a, 0x4a]:
+        ret = 0
+    else:
+        raise ValueError('unimpl index')
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def wsock32_WSAStartup(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    version, pwsadata = args
+    myjit.vm.vm_set_mem(pwsadata, "\x01\x01\x02\x02WinSock 2.0\x00")
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_GetLocalTime(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    lpsystemtime, = args
+
+    s = struct.pack('HHHHHHHH',
+                    2011,  # year
+                    10,   # month
+                    5,    # dayofweek
+                    7,    # day
+                    13,   # hour
+                    37,   # minutes
+                    00,   # seconds
+                    999,  # millisec
+                    )
+    myjit.vm.vm_set_mem(lpsystemtime, s)
+    myjit.func_ret_stdcall(ret_ad, lpsystemtime)
+
+
+def kernel32_GetSystemTime(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    lpsystemtime, = args
+
+    print whoami(), hex(ret_ad), hex(lpsystemtime)
+
+    s = struct.pack('HHHHHHHH',
+                    2011,  # year
+                    10,   # month
+                    5,    # dayofweek
+                    7,    # day
+                    13,   # hour
+                    37,   # minutes
+                    00,   # seconds
+                    999,  # millisec
+                    )
+    myjit.vm.vm_set_mem(lpsystemtime, s)
+    myjit.func_ret_stdcall(ret_ad, lpsystemtime)
+
+
+def kernel32_CreateFileMapping(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(6)
+    hfile, lpattr, flprotect, dwmaximumsizehigh, dwmaximumsizelow, lpname = args
+
+    if lpname:
+        f = get_str(myjit, lpname)
+    else:
+        f = None
+    print repr(f)
+
+    if not hfile in winobjs.handle_pool:
+        raise ValueError('unknown handle')
+
+    ret = winobjs.handle_pool.add('filemapping', hfile)
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_CreateFileMappingA(myjit):
+    kernel32_CreateFileMapping(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_CreateFileMappingW(myjit):
+    kernel32_CreateFileMapping(myjit, whoami(), get_str_unic)
+
+
+def kernel32_MapViewOfFile(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hfile, flprotect, dwfileoffsethigh, dwfileoffsetlow, length = args
+
+    if not hfile in winobjs.handle_pool:
+        raise ValueError('unknown handle')
+    hmap = winobjs.handle_pool[hfile]
+    print hmap
+    if not hmap.info in winobjs.handle_pool:
+        raise ValueError('unknown file handle')
+
+    hfile_o = winobjs.handle_pool[hmap.info]
+    print hfile_o
+    fd = hfile_o.info
+    fd.seek((dwfileoffsethigh << 32) | dwfileoffsetlow)
+    if length:
+        data = fd.read(length)
+    else:
+        data = fd.read()
+    length = len(data)
+
+    print 'mapp total:', hex(len(data))
+    access_dict = {0x0: 0,
+                   0x1: 0,
+                   0x2: PAGE_READ,
+                   0x4: PAGE_READ | PAGE_WRITE,
+                   0x10: PAGE_EXEC,
+                   0x20: PAGE_EXEC | PAGE_READ,
+                   0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                   0x100: 0
+                       }
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+    if not flprotect in access_dict:
+        raise ValueError('unknown access dw!')
+
+    alloc_addr = alloc_mem(myjit, len(data))
+    myjit.vm.vm_set_mem(alloc_addr, data)
+
+    winobjs.handle_mapped[
+        alloc_addr] = hfile_o, dwfileoffsethigh, dwfileoffsetlow, length
+    print 'return', hex(alloc_addr)
+
+    myjit.func_ret_stdcall(ret_ad, alloc_addr)
+
+
+def kernel32_UnmapViewOfFile(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    ad, = args
+
+    if not ad in winobjs.handle_mapped:
+        raise NotImplementedError("Untested case")
+    """
+    hfile_o, dwfileoffsethigh, dwfileoffsetlow, length = winobjs.handle_mapped[ad]
+    off = (dwfileoffsethigh<<32) | dwfileoffsetlow
+    s = myjit.vm.vm_get_mem(ad, length)
+    hfile_o.info.seek(off)
+    hfile_o.info.write(s)
+    hfile_o.info.close()
+    """
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetDriveType(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    pathname, = args
+
+    print funcname, hex(pathname)
+
+    p = get_str(myjit, pathname)
+    print repr(p)
+    p = p.upper()
+
+    ret = 0
+    if p[0] == "C":
+        ret = 3
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetDriveTypeA(myjit):
+    kernel32_GetDriveType(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_GetDriveTypeW(myjit):
+    kernel32_GetDriveType(myjit, whoami(), get_str_unic)
+
+
+def kernel32_GetDiskFreeSpace(myjit, funcname, get_str):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    (lprootpathname, lpsectorpercluster, lpbytespersector,
+     lpnumberoffreeclusters, lptotalnumberofclusters) = args
+
+    if lprootpathname:
+        rootpath = get_str(myjit, lprootpathname)
+    else:
+        rootpath = ""
+    print repr(rootpath)
+
+    myjit.vm.vm_set_mem(lpsectorpercluster, pck32(8))
+    myjit.vm.vm_set_mem(lpbytespersector, pck32(0x200))
+    myjit.vm.vm_set_mem(lpnumberoffreeclusters, pck32(0x222222))
+    myjit.vm.vm_set_mem(lptotalnumberofclusters, pck32(0x333333))
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_GetDiskFreeSpaceA(myjit):
+    kernel32_GetDiskFreeSpace(myjit, whoami(), get_str_ansi)
+
+
+def kernel32_GetDiskFreeSpaceW(myjit):
+    kernel32_GetDiskFreeSpace(myjit, whoami(), get_str_unic)
+
+
+def kernel32_VirtualQuery(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    ad, lpbuffer, dwl = args
+
+    access_dict = {0x0: 0,
+                   0x1: 0,
+                   0x2: PAGE_READ,
+                   0x4: PAGE_READ | PAGE_WRITE,
+                   0x10: PAGE_EXEC,
+                   0x20: PAGE_EXEC | PAGE_READ,
+                   0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                   0x100: 0
+                       }
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+    all_mem = myjit.vm.vm_get_all_memory()
+    found = None
+    for basead, m in all_mem.items():
+        if basead <= ad < basead + m['size']:
+            found = ad, m
+            break
+    if not found:
+        raise ValueError('cannot find mem', hex(ad))
+
+    if dwl != 0x1c:
+        raise ValueError('strange mem len', hex(dwl))
+    s = struct.pack('IIIIIII',
+                    ad,
+                    basead,
+                    access_dict_inv[m['access']],
+                    m['size'],
+                    0x1000,
+                    access_dict_inv[m['access']],
+                    0x01000000)
+    myjit.vm.vm_set_mem(lpbuffer, s)
+
+    myjit.func_ret_stdcall(ret_ad, dwl)
+
+
+def kernel32_GetProcessAffinityMask(myjit):
+    ret_ad, args = myjit.func_args_stdcall(3)
+    hprocess, procaffmask, systemaffmask = args
+    myjit.vm.vm_set_mem(procaffmask, pck32(1))
+    myjit.vm.vm_set_mem(systemaffmask, pck32(1))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def msvcrt_rand(myjit):
+    ret_ad, args = myjit.func_args_cdecl(0)
+    myjit.func_ret_stdcall(ret_ad, 0x666)
+
+
+def kernel32_SetFilePointer(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    hwnd, distance, p_distance_high, movemethod = args
+
+    if hwnd == winobjs.module_cur_hwnd:
+        pass
+    elif hwnd in winobjs.handle_pool:
+        pass
+    else:
+        raise ValueError('unknown hwnd!')
+
+    eax = 0xffffffff
+    data = None
+    if hwnd in winobjs.files_hwnd:
+        winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(distance)
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        data = wh.info.seek(distance)
+    else:
+        raise ValueError('unknown filename')
+    myjit.func_ret_stdcall(ret_ad, distance)
+
+
+def kernel32_SetFilePointerEx(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    hwnd, distance_l, distance_h, pnewfileptr, movemethod = args
+
+    distance = distance_l | (distance_h << 32)
+    if distance:
+        TODO_XXX
+
+    if pnewfileptr:
+        TODO_XXX
+    if hwnd == winobjs.module_cur_hwnd:
+        pass
+    elif hwnd in winobjs.handle_pool:
+        pass
+    else:
+        raise ValueError('unknown hwnd!')
+
+    eax = 0xffffffff
+    data = None
+    if hwnd in winobjs.files_hwnd:
+        winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(distance)
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        data = wh.info.seek(distance)
+    else:
+        raise ValueError('unknown filename')
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_SetEndOfFile(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hwnd, = args
+    if hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        wh.info.seek(0, 2)
+    else:
+        raise ValueError('unknown filename')
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_FlushFileBuffers(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    hwnd, = args
+    if hwnd in winobjs.handle_pool:
+        pass
+    else:
+        raise ValueError('unknown filename')
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def kernel32_WriteFile(myjit):
+    ret_ad, args = myjit.func_args_stdcall(5)
+    (hwnd, lpbuffer, nnumberofbytestowrite,
+     lpnumberofbyteswrite, lpoverlapped) = args
+
+    data = myjit.vm.vm_get_mem(lpbuffer, nnumberofbytestowrite)
+
+    if hwnd == winobjs.module_cur_hwnd:
+        pass
+    elif hwnd in winobjs.handle_pool:
+        pass
+    else:
+        raise ValueError('unknown hwnd!')
+
+    eax = 0xffffffff
+    if hwnd in winobjs.files_hwnd:
+        winobjs.files_hwnd[winobjs.module_cur_hwnd].write(data)
+    elif hwnd in winobjs.handle_pool:
+        wh = winobjs.handle_pool[hwnd]
+        wh.info.write(data)
+    else:
+        raise ValueError('unknown filename')
+
+    if (lpnumberofbyteswrite):
+        myjit.vm.vm_set_mem(lpnumberofbyteswrite, pck32(len(data)))
+
+    myjit.func_ret_stdcall(ret_ad, 1)
+
+
+def user32_IsCharUpperA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    c, = args
+
+    if c & 0x20:
+        ret = 0
+    else:
+        ret = 1
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def user32_IsCharLowerA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    c, = args
+
+    if c & 0x20:
+        ret = 1
+    else:
+        ret = 0
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetSystemDefaultLangID(myjit):
+    ret_ad, args = myjit.func_args_stdcall(0)
+    myjit.func_ret_stdcall(ret_ad, 0x409)  # encglish
+
+
+def msvcrt_malloc(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    msize, = args
+    addr = alloc_mem(myjit, msize)
+    myjit.func_ret_cdecl(ret_ad, addr)
+
+
+def msvcrt_free(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    ptr, = args
+    myjit.func_ret_cdecl(ret_ad, 0)
+
+
+def msvcrt_fopen(myjit):
+    ret_ad, args = myjit.func_args_cdecl(2)
+    fname, rw = args
+
+    fname = get_str_ansi(myjit, fname)
+    rw = get_str_ansi(myjit, rw)
+    print fname, rw
+    if rw in ['rb', 'wb+']:
+        fname = fname.replace('\\', "/").lower()
+        f = os.path.join('file_sb', fname)
+        h = open(f, rw)
+        eax = winobjs.handle_pool.add(f, h)
+        alloc_addr = alloc_mem(myjit, 0x20)
+        myjit.vm.vm_set_mem(alloc_addr, pck32(0x11112222) + pck32(
+            0) + pck32(0) + pck32(0) + pck32(eax))  # pck32(0x11112222)
+    else:
+        raise NotImplementedError("Untested case")
+
+    myjit.func_ret_cdecl(ret_ad, alloc_addr)
+
+
+def msvcrt_fseek(myjit):
+    ret_ad, args = myjit.func_args_cdecl(3)
+    stream, offset, orig = args
+    fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4))
+    print hex(fd)
+
+    if not fd in winobjs.handle_pool:
+        raise NotImplementedError("Untested case")
+    o = winobjs.handle_pool[fd]
+    o.info.seek(offset, orig)
+    myjit.func_ret_cdecl(ret_ad, 0)
+
+
+def msvcrt_ftell(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    stream, = args
+    fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4))
+    print hex(fd)
+
+    if not fd in winobjs.handle_pool:
+        raise NotImplementedError("Untested case")
+    o = winobjs.handle_pool[fd]
+    off = o.info.tell()
+    myjit.func_ret_cdecl(ret_ad, off)
+
+
+def msvcrt_rewind(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    stream, = args
+    fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4))
+    print hex(fd)
+
+    if not fd in winobjs.handle_pool:
+        raise NotImplementedError("Untested case")
+    o = winobjs.handle_pool[fd]
+    off = o.info.seek(0, 0)
+    myjit.func_ret_cdecl(ret_ad, 0)
+
+
+def msvcrt_fread(myjit):
+    ret_ad, args = myjit.func_args_cdecl(4)
+    buf, size, nmemb, stream = args
+    fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4))
+    print hex(fd)
+    if not fd in winobjs.handle_pool:
+        raise NotImplementedError("Untested case")
+
+    data = winobjs.handle_pool[fd].info.read(size * nmemb)
+    myjit.vm.vm_set_mem(buf, data)
+    myjit.func_ret_cdecl(ret_ad, nmemb)
+
+
+def msvcrt_fclose(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    stream, = args
+    fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4))
+    print hex(fd)
+
+    if not fd in winobjs.handle_pool:
+        raise NotImplementedError("Untested case")
+    o = winobjs.handle_pool[fd]
+    off = o.info.close()
+    myjit.func_ret_cdecl(ret_ad, 0)
+
+
+def msvcrt_atexit(myjit):
+    ret_ad, args = myjit.func_args_cdecl(1)
+    func, = args
+    myjit.func_ret_cdecl(ret_ad, 0)
+
+
+def user32_MessageBoxA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(4)
+    hwnd, lptext, lpcaption, utype = args
+
+    text = get_str_ansi(myjit, lptext)
+    caption = get_str_ansi(myjit, lpcaption)
+
+    print 'Caption:', repr(caption), 'Text:', repr(text)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def kernel32_myGetTempPath(myjit, func):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    l, buf = args
+
+    l = 'c:\\temp\\'
+    myjit.vm.vm_set_mem(buf, func(l + '\x00'))
+    myjit.func_ret_stdcall(ret_ad, len(l))
+
+
+def kernel32_GetTempPathA(myjit):
+    kernel32_myGetTempPath(myjit, set_str_ansi)
+
+
+def kernel32_GetTempPathW(myjit):
+    kernel32_myGetTempPath(myjit, set_str_unic)
+
+
+temp_num = 0
+
+
+def kernel32_GetTempFileNameA(myjit):
+    global temp_num
+    ret_ad, args = myjit.func_args_stdcall(4)
+    path, ext, unique, buf = args
+
+    temp_num += 1
+    if ext:
+        ext = get_str_ansi(myjit, ext)
+    else:
+        ext = 'tmp'
+    if path:
+        path = get_str_ansi(myjit, path)
+    else:
+        path = "xxx"
+    print ext, path
+    fname = path + "\\" + "temp%.4d" % temp_num + "." + ext
+    print fname
+    myjit.vm.vm_set_mem(buf, fname)
+
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+class win32_find_data:
+    fileattrib = 0
+    creationtime = 0
+    lastaccesstime = 0
+    lastwritetime = 0
+    filesizehigh = 0
+    filesizelow = 0
+    dwreserved0 = 0
+    dwreserved1 = 0x1337beef
+    cfilename = ""
+    alternamefilename = ""
+
+    def __init__(self, **kargs):
+        for k, v in kargs.items():
+            setattr(self, k, v)
+
+    def toStruct(self):
+        s = struct.pack('=IQQQIIII',
+                        self.fileattrib,
+                        self.creationtime,
+                        self.lastaccesstime,
+                        self.lastwritetime,
+                        self.filesizehigh,
+                        self.filesizelow,
+                        self.dwreserved0,
+                        self.dwreserved1)
+        fname = self.cfilename + '\x00' * win_api_x86_32.MAX_PATH
+        fname = fname[:win_api_x86_32.MAX_PATH]
+        s += fname
+        fname = self.alternamefilename + '\x00' * 14
+        fname = fname[:14]
+        s += fname
+        return s
+
+
+class find_data_mngr:
+
+    def __init__(self):
+        self.patterns = {}
+        self.flist = []
+        # handle number -> (flist index, current index in list)
+        self.handles = {}
+
+    def add_list(self, pattern, flist):
+        index = len(self.flist)
+        self.flist.append(flist)
+
+        self.patterns[pattern] = index
+
+    def findfirst(self, pattern):
+        assert(pattern in self.patterns)
+        findex = self.patterns[pattern]
+        h = len(self.handles) + 1
+        self.handles[h] = [findex, 0]
+        return h
+
+    def findnext(self, h):
+        assert(h in self.handles)
+        findex, index = self.handles[h]
+        if index >= len(self.flist[findex]):
+            return None
+        fname = self.flist[findex][index]
+        self.handles[h][1] += 1
+
+        return fname
+
+
+def kernel32_FindFirstFileA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    pfilepattern, pfindfiledata = args
+
+    filepattern = get_str_ansi(myjit, pfilepattern)
+    print repr(filepattern)
+    h = winobjs.find_data.findfirst(filepattern)
+
+    fname = winobjs.find_data.findnext(h)
+    fdata = win32_find_data(cfilename=fname)
+
+    myjit.vm.vm_set_mem(pfindfiledata, fdata.toStruct())
+    myjit.func_ret_stdcall(ret_ad, h)
+
+
+def kernel32_FindNextFileA(myjit):
+    ret_ad, args = myjit.func_args_stdcall(2)
+    handle, pfindfiledata = args
+
+    fname = winobjs.find_data.findnext(handle)
+    if fname is None:
+        ret = 0
+    else:
+        ret = 1
+        fdata = win32_find_data(cfilename=fname)
+        myjit.vm.vm_set_mem(pfindfiledata, fdata.toStruct())
+
+    myjit.func_ret_stdcall(ret_ad, ret)
+
+
+def kernel32_GetNativeSystemInfo(myjit):
+    ret_ad, args = myjit.func_args_stdcall(1)
+    sys_ptr, = args
+    sysinfo = systeminfo()
+    myjit.vm.vm_set_mem(sys_ptr, sysinfo.pack())
+    myjit.func_ret_stdcall(ret_ad, 0)
+
+
+def raw2guid(r):
+    o = struct.unpack('IHHHBBBBBB', r)
+    return '{%.8X-%.4X-%.4X-%.4X-%.2X%.2X%.2X%.2X%.2X%.2X}' % o
+
+
+digs = string.digits + string.lowercase
+
+
+def int2base(x, base):
+    if x < 0:
+        sign = -1
+    elif x == 0:
+        return '0'
+    else:
+        sign = 1
+    x *= sign
+    digits = []
+    while x:
+        digits.append(digs[x % base])
+        x /= base
+    if sign < 0:
+        digits.append('-')
+    digits.reverse()
+    return ''.join(digits)
+
+
+def msvcrt__ultow(myjit):
+    ret_ad, args = myjit.func_args_cdecl(3)
+    value, p, radix = args
+
+    value &= 0xFFFFFFFF
+    if not radix in [10, 16, 20]:
+        TODO_TEST
+    s = int2base(value, radix)
+    myjit.vm.vm_set_mem(p, set_str_unic(s + "\x00"))
+    myjit.func_ret_cdecl(ret_ad, p)
+
+
+def msvcrt_myfopen(myjit, func):
+    ret_ad, args = myjit.func_args_cdecl(2)
+    pfname, pmode = args
+
+
+    fname = func(myjit, pfname)
+    rw = func(myjit, pmode)
+    print repr(fname)
+    print repr(rw)
+
+    if rw in ['r', 'rb', 'wb+']:
+        fname = fname.replace('\\', "/").lower()
+        f = os.path.join('file_sb', fname)
+        h = open(f, rw)
+        eax = winobjs.handle_pool.add(f, h)
+        dwsize = 0x20
+        alloc_addr = alloc_mem(myjit, dwsize)
+        pp = pck32(0x11112222)+pck32(0)+pck32(0)+pck32(0)+pck32(eax)#pdw(0x11112222)
+        myjit.vm.vm_set_mem(alloc_addr, pp)
+
+
+    else:
+        raise ValueError('unknown access mode %s'%rw)
+
+    myjit.func_ret_cdecl(ret_ad, alloc_addr)
+
+def msvcrt__wfopen(myjit):
+    msvcrt_myfopen(myjit, get_str_unic)
+
+def msvcrt_fopen(myjit):
+    msvcrt_myfopen(myjit, get_str_ansi)
diff --git a/miasm2/jitter/os_dep/win_api_x86_32_seh.py b/miasm2/jitter/os_dep/win_api_x86_32_seh.py
new file mode 100644
index 00000000..4136c592
--- /dev/null
+++ b/miasm2/jitter/os_dep/win_api_x86_32_seh.py
@@ -0,0 +1,896 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import logging
+from elfesteem import pe_init
+from miasm2.jitter.vm_mngr import *
+from miasm2.jitter.csts import *
+from miasm2.core.utils import *
+from miasm2.arch import x86
+import os
+
+# Constants Windows
+EXCEPTION_BREAKPOINT = 0x80000003
+EXCEPTION_ACCESS_VIOLATION = 0xc0000005
+EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094
+EXCEPTION_PRIV_INSTRUCTION = 0xc0000096
+EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d
+
+
+log = logging.getLogger("seh_helper")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARN)
+
+FS_0_AD = 0x7ff70000
+PEB_AD = 0x7ffdf000
+LDR_AD = 0x340000
+
+MAX_MODULES = 0x40
+
+# fs:[0] Page (TIB)
+tib_address = FS_0_AD
+peb_address = PEB_AD
+peb_ldr_data_offset = 0x1ea0
+peb_ldr_data_address = LDR_AD + peb_ldr_data_offset  # PEB_AD + 0x1000
+
+
+modules_list_offset = 0x1f00
+
+InInitializationOrderModuleList_offset = 0x1ee0  # 0x1f48
+InInitializationOrderModuleList_address = LDR_AD + \
+    InInitializationOrderModuleList_offset  # PEB_AD + 0x2000
+
+InLoadOrderModuleList_offset = 0x1ee0 + \
+    MAX_MODULES * 0x1000  # 0x1f48 + MAX_MODULES*0x1000
+InLoadOrderModuleList_address = LDR_AD + \
+    InLoadOrderModuleList_offset  # PEB_AD + 0x2000
+
+# in_load_order_module_1 = LDR_AD +
+# in_load_order_module_list_offset#PEB_AD + 0x3000
+default_seh = PEB_AD + 0x20000
+
+process_environment_address = 0x10000
+process_parameters_address = 0x200000
+
+context_address = 0x201000
+exception_record_address = context_address + 0x1000
+return_from_exception = 0x6eadbeef
+
+FAKE_SEH_B_AD = context_address + 0x2000
+
+cur_seh_ad = FAKE_SEH_B_AD
+
+loaded_modules = ["ntdll.dll", "kernel32.dll"]
+main_pe = None
+main_pe_name = "c:\\xxx\\toto.exe"
+
+
+def build_fake_teb():
+    """
+    +0x000 NtTib                     : _NT_TIB
+    +0x01c EnvironmentPointer        : Ptr32 Void
+    +0x020 ClientId                  : _CLIENT_ID
+    +0x028 ActiveRpcHandle           : Ptr32 Void
+    +0x02c ThreadLocalStoragePointer : Ptr32 Void
+    +0x030 ProcessEnvironmentBlock   : Ptr32 _PEB
+    +0x034 LastErrorValue            : Uint4B
+    ...
+    """
+    o = ""
+    o += pck32(default_seh)
+    o += (0x18 - len(o)) * "\x00"
+    o += pck32(tib_address)
+
+    o += (0x30 - len(o)) * "\x00"
+    o += pck32(peb_address)
+    o += pck32(0x11223344)
+
+    return o
+
+
+def build_fake_peb():
+    """
+    +0x000 InheritedAddressSpace    : UChar
+    +0x001 ReadImageFileExecOptions : UChar
+    +0x002 BeingDebugged            : UChar
+    +0x003 SpareBool                : UChar
+    +0x004 Mutant                   : Ptr32 Void
+    +0x008 ImageBaseAddress         : Ptr32 Void
+    +0x00c Ldr                      : Ptr32 _PEB_LDR_DATA
+    +0x010 processparameter
+    """
+
+    offset_serverdata = 0x100
+    offset_data1 = 0x108
+    offset_data2 = 0x110
+    o = ""
+    o += "\x00" * 0x8
+    if main_pe:
+        o += pck32(main_pe.NThdr.ImageBase)
+    else:
+        o += "AAAA"
+    o += pck32(peb_ldr_data_address)
+    o += pck32(process_parameters_address)
+
+    o += (0x54 - len(o)) * "A"
+    o += pck32(peb_address + offset_serverdata)
+    o += (0x64 - len(o)) * "E"
+    o += pck32(1)  # number of cpu
+
+    o += (offset_serverdata - len(o)) * "B"
+    o += pck32(0x33333333)
+    o += pck32(peb_address + offset_data1)
+    o += (offset_data1 - len(o)) * "C"
+    o += pck32(0x44444444)
+    o += pck32(peb_address + offset_data2)
+    o += (offset_data2 - len(o)) * "D"
+    o += pck32(0x55555555)
+    o += pck32(0x0077007C)
+    return o
+
+
+def build_fake_ldr_data(modules_info):
+    """
+    +0x000 Length                          : Uint4B
+    +0x004 Initialized                     : UChar
+    +0x008 SsHandle                        : Ptr32 Void
+    +0x00c InLoadOrderModuleList           : _LIST_ENTRY
+    +0x014 InMemoryOrderModuleList         : _LIST_ENTRY
+    +0x01C InInitializationOrderModuleList         : _LIST_ENTRY
+    """
+    o = ""
+    # ldr offset pad
+    o += "\x00" * peb_ldr_data_offset
+    o += "\x00" * 0xc
+    # text XXX
+
+    # get main pe info
+    m_e = None
+    for bname, (addr, e) in modules_info.items():
+        if e == main_pe:
+            m_e = (e, bname, addr)
+            break
+    if not m_e:
+        log.warn('no main pe, ldr data will be unconsistant')
+    else:
+        print 'inloadorder first', hex(m_e[2])
+        o += pck32(m_e[2]) + pck32(0)
+
+    # get ntdll
+    ntdll_e = None
+    for bname, (addr, e) in modules_info.items():
+        if bname[::2].lower() == "ntdll.dll":
+            ntdll_e = (e, bname, addr)
+            continue
+    if not ntdll_e:
+        log.warn('no ntdll, ldr data will be unconsistant')
+    else:
+        print 'ntdll', hex(ntdll_e[2])
+        o += pck32(ntdll_e[2] + 0x8) + pck32(0)  # XXX TODO
+        o += pck32(ntdll_e[2] + 0x10) + pck32(0)
+
+    return o
+
+# def build_fake_InInitializationOrderModuleList(modules_name):
+#    """
+#    +0x000 Flink : Ptr32                                 -+ This distance
+#    +0x004 Blink : Ptr32                                  | is eight bytes
+#    +0x018 DllBase                        : Ptr32 Void   -+ DllBase
+#    +0x01c EntryPoint                     : Ptr32 Void
+#    +0x020 SizeOfImage                    : Uint4B
+#    +0x024 FullDllName                    : _UNICODE_STRING
+#    +0x02c BaseDllName                    : _UNICODE_STRING
+#    +0x034 Flags                          : Uint4B
+#    +0x038 LoadCount                      : Uint2B
+#    +0x03a TlsIndex                       : Uint2B
+#    +0x03c HashLinks                      : _LIST_ENTRY
+#    +0x03c SectionPointer                 : Ptr32 Void
+#    +0x040 CheckSum                       : Uint4B
+#    +0x044 TimeDateStamp                  : Uint4B
+#    +0x044 LoadedImports                  : Ptr32 Void
+#    +0x048 EntryPointActivationContext    : Ptr32 Void
+#    +0x04c PatchInformation               : Ptr32 Void
+#    """
+#
+#    o = ""
+#    offset_name = 0x700
+#    for i, m in enumerate(modules_name):
+# fname = os.path.join('win_dll', m)
+#        if isinstance(m, tuple):
+#            fname, e = m
+#        else:
+#            fname, e = m, None
+#        bname = os.path.split(fname)[1].lower()
+#        bname = "\x00".join(bname)+"\x00"
+#        print "add module", repr(bname)
+#        print hex(InInitializationOrderModuleList_address+i*0x1000)
+#        if e == None:
+#            e = pe_init.PE(open(fname, 'rb').read())
+#
+#        next_ad = InInitializationOrderModuleList_address + (i+1)*0x1000
+#        if i == len(modules_name) -1:
+#            next_ad = InInitializationOrderModuleList_address
+#        m_o = ""
+#        m_o += pck32(next_ad )
+#        m_o += pck32(InInitializationOrderModuleList_address + (i-1)*0x1000)
+#        m_o += pck32(next_ad + 8 )
+#        m_o += pck32(InInitializationOrderModuleList_address
+#            +  (i-1)*0x1000 + 8)
+#        m_o += pck32(next_ad + 0x10 )
+#        m_o += pck32(InInitializationOrderModuleList_address
+#            +  (i-1)*0x1000 + 0x10)
+#        m_o += pck32(e.NThdr.ImageBase)
+#        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
+#        m_o += pck32(e.NThdr.sizeofimage)
+#
+#        m_o += (0x24 - len(m_o))*"A"
+#        print hex(len(bname)), repr(bname)
+#        m_o += struct.pack('HH', len(bname), len(bname)+2)
+#        m_o += pck32(InInitializationOrderModuleList_address
+#            +  i*0x1000+offset_name)
+#
+#        m_o += (0x2C - len(m_o))*"A"
+#        m_o += struct.pack('HH', len(bname), len(bname)+2)
+#        m_o += pck32(InInitializationOrderModuleList_address
+#            +  i*0x1000+offset_name)
+#
+#        m_o += (offset_name - len(m_o))*"B"
+#        m_o += bname
+#        m_o += "\x00"*3
+#
+#
+#        m_o += (0x1000 - len(m_o))*"J"
+#
+#        print "module", "%.8X"%e.NThdr.ImageBase, fname
+#
+#        o += m_o
+#    return o
+#
+dummy_e = pe_init.PE()
+dummy_e.NThdr.ImageBase = 0
+dummy_e.Opthdr.AddressOfEntryPoint = 0
+dummy_e.NThdr.sizeofimage = 0
+
+
+def create_modules_chain(myjit, modules_name):
+    modules_info = {}
+    base_addr = LDR_AD + modules_list_offset  # XXXX
+    offset_name = 0x500
+    offset_path = 0x600
+
+    out = ""
+    for i, m in enumerate([(main_pe_name, main_pe),
+        ("", dummy_e)] + modules_name):
+        addr = base_addr + i * 0x1000
+        # fname = os.path.join('win_dll', m)
+        if isinstance(m, tuple):
+            fname, e = m
+        else:
+            fname, e = m, None
+        bpath = fname.replace('/', '\\')
+        bname = os.path.split(fname)[1].lower()
+        bname = "\x00".join(bname) + "\x00"
+        # print "add module", repr(bname), repr(bpath)
+        # print hex(InInitializationOrderModuleList_address+i*0x1000)
+        if e is None:
+            if i == 0:
+                full_name = fname
+            else:
+                full_name = os.path.join("win_dll", fname)
+            try:
+                e = pe_init.PE(open(full_name, 'rb').read())
+            except IOError:
+                log.error('no main pe, ldr data will be unconsistant!!')
+                e = None
+        if e is None:
+            continue
+        print "add module", hex(e.NThdr.ImageBase), repr(bname)
+
+        modules_info[bname] = addr, e
+
+        m_o = ""
+        m_o += pck32(0)
+        m_o += pck32(0)
+        m_o += pck32(0)
+        m_o += pck32(0)
+        m_o += pck32(0)
+        m_o += pck32(0)
+        m_o += pck32(e.NThdr.ImageBase)
+        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
+        m_o += pck32(e.NThdr.sizeofimage)
+
+        m_o += (0x24 - len(m_o)) * "A"
+        print hex(len(bname)), repr(bname)
+        m_o += struct.pack('HH', len(bname), len(bname) + 2)
+        m_o += pck32(addr + offset_path)
+
+        m_o += (0x2C - len(m_o)) * "A"
+        m_o += struct.pack('HH', len(bname), len(bname) + 2)
+        m_o += pck32(addr + offset_name)
+
+        m_o += (offset_name - len(m_o)) * "B"
+        m_o += bname
+        m_o += "\x00" * 3
+
+        m_o += (offset_path - len(m_o)) * "B"
+        m_o += "\x00".join(bpath) + "\x00"
+        m_o += "\x00" * 3
+        # out += m_o
+        myjit.vm.vm_set_mem(addr, m_o)
+    return modules_info
+
+
+def fix_InLoadOrderModuleList(myjit, module_info):
+    print "fix inloadorder"
+    # first binary is PE
+    # last is dumm_e
+    olist = []
+    m_e = None
+    d_e = None
+    for m in [main_pe_name, ""] + loaded_modules:
+
+        if isinstance(m, tuple):
+            fname, e = m
+        else:
+            fname, e = m, None
+
+        if "/" in fname:
+            fname = fname[fname.rfind("/") + 1:]
+        bname = '\x00'.join(fname) + '\x00'
+        if not bname.lower() in module_info:
+            log.warn('module not found, ldr data will be unconsistant')
+            continue
+
+        addr, e = module_info[bname.lower()]
+    # for bname, (addr, e) in module_info.items():
+        print bname
+        if e == main_pe:
+            m_e = (e, bname, addr)
+            continue
+        elif e == dummy_e:
+            d_e = (e, bname, addr)
+            continue
+        olist.append((e, bname, addr))
+    if not m_e or not d_e:
+        log.warn('no main pe, ldr data will be unconsistant')
+    else:
+        olist[0:0] = [m_e]
+    olist.append(d_e)
+
+    last_addr = 0
+    for i in xrange(len(olist)):
+        e, bname, addr = olist[i]
+        p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
+        n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
+        myjit.vm.vm_set_mem(addr + 0, pck32(n_addr) + pck32(p_addr))
+
+
+def fix_InMemoryOrderModuleList(myjit, module_info):
+    # first binary is PE
+    # last is dumm_e
+    olist = []
+    m_e = None
+    d_e = None
+    for m in [main_pe_name, ""] + loaded_modules:
+
+        if isinstance(m, tuple):
+            fname, e = m
+        else:
+            fname, e = m, None
+
+        if "/" in fname:
+            fname = fname[fname.rfind("/") + 1:]
+        bname = '\x00'.join(fname) + '\x00'
+        if not bname.lower() in module_info:
+            log.warn('module not found, ldr data will be unconsistant')
+            continue
+        addr, e = module_info[bname.lower()]
+    # for bname, (addr, e) in module_info.items():
+        print bname
+        if e == main_pe:
+            m_e = (e, bname, addr)
+            continue
+        elif e == dummy_e:
+            d_e = (e, bname, addr)
+            continue
+        olist.append((e, bname, addr))
+    if not m_e or not d_e:
+        log.warn('no main pe, ldr data will be unconsistant')
+    else:
+        olist[0:0] = [m_e]
+    olist.append(d_e)
+
+    last_addr = 0
+
+    for i in xrange(len(olist)):
+        e, bname, addr = olist[i]
+        p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
+        n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
+        myjit.vm.vm_set_mem(
+            addr + 0x8, pck32(n_addr + 0x8) + pck32(p_addr + 0x8))
+
+
+def fix_InInitializationOrderModuleList(myjit, module_info):
+    # first binary is ntdll
+    # second binary is kernel32
+    olist = []
+    ntdll_e = None
+    kernel_e = None
+    for bname, (addr, e) in module_info.items():
+        if bname[::2].lower() == "ntdll.dll":
+            ntdll_e = (e, bname, addr)
+            continue
+        elif bname[::2].lower() == "kernel32.dll":
+            kernel_e = (e, bname, addr)
+            continue
+        elif e == dummy_e:
+            d_e = (e, bname, addr)
+            continue
+        elif e == main_pe:
+            continue
+        olist.append((e, bname, addr))
+    if not ntdll_e or not kernel_e or not d_e:
+        log.warn('no kernel ntdll, ldr data will be unconsistant')
+    else:
+        olist[0:0] = [ntdll_e]
+        olist[1:1] = [kernel_e]
+
+    olist.append(d_e)
+
+    last_addr = 0
+    for i in xrange(len(olist)):
+        e, bname, addr = olist[i]
+        p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
+        n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
+        myjit.vm.vm_set_mem(
+            addr + 0x10, pck32(n_addr + 0x10) + pck32(p_addr + 0x10))
+
+
+def add_process_env(myjit):
+    env_str = 'ALLUSEESPROFILE=C:\\Documents and Settings\\All Users\x00'
+    env_str = '\x00'.join(env_str)
+    env_str += "\x00" * 0x10
+    myjit.vm.vm_add_memory_page(process_environment_address,
+                                PAGE_READ | PAGE_WRITE,
+                                env_str)
+    myjit.vm.vm_set_mem(process_environment_address, env_str)
+
+
+def add_process_parameters(myjit):
+    o = ""
+    o += pck32(0x1000)  # size
+    o += "E" * (0x48 - len(o))
+    o += pck32(process_environment_address)
+    myjit.vm.vm_add_memory_page(process_parameters_address,
+                                PAGE_READ | PAGE_WRITE,
+                                o)
+
+
+def build_fake_InLoadOrderModuleList(modules_name):
+    """
+    +0x000 Flink : Ptr32                                 -+ This distance
+    +0x004 Blink : Ptr32                                  | is eight bytes
+    +0x018 DllBase                        : Ptr32 Void   -+ DllBase -> _IMAGE_DOS_HEADER
+    +0x01c EntryPoint                     : Ptr32 Void
+    +0x020 SizeOfImage                    : Uint4B
+    +0x024 FullDllName                    : _UNICODE_STRING
+    +0x02c BaseDllName                    : _UNICODE_STRING
+    +0x034 Flags                          : Uint4B
+    +0x038 LoadCount                      : Uint2B
+    +0x03a TlsIndex                       : Uint2B
+    +0x03c HashLinks                      : _LIST_ENTRY
+    +0x03c SectionPointer                 : Ptr32 Void
+    +0x040 CheckSum                       : Uint4B
+    +0x044 TimeDateStamp                  : Uint4B
+    +0x044 LoadedImports                  : Ptr32 Void
+    +0x048 EntryPointActivationContext    : Ptr32 Void
+    +0x04c PatchInformation               : Ptr32 Void
+    """
+
+    o = ""
+    offset_name = 0x700
+    first_name = "\x00".join(main_pe_name + "\x00\x00")
+
+    o = ""
+    o += pck32(InLoadOrderModuleList_address)
+    o += pck32(InLoadOrderModuleList_address +
+               (len(modules_name) - 1) * 0x1000)
+    o += pck32(InLoadOrderModuleList_address + 8)
+    o += pck32(InLoadOrderModuleList_address +
+               (len(modules_name) - 1) * 0x1000 + 8)
+    o += pck32(InLoadOrderModuleList_address + 0x10)
+    o += pck32(InLoadOrderModuleList_address +
+               (len(modules_name) - 1) * 0x1000 + 0x10)
+
+    if main_pe:
+        o += pck32(main_pe.NThdr.ImageBase)
+        o += pck32(main_pe.rva2virt(main_pe.Opthdr.AddressOfEntryPoint))
+    else:
+        # no fixed values
+        pass
+
+    o += (0x24 - len(o)) * "A"
+    o += struct.pack('HH', len(first_name), len(first_name))
+    o += pck32(InLoadOrderModuleList_address + offset_name)
+
+    o += (0x2C - len(o)) * "A"
+    o += struct.pack('HH', len(first_name), len(first_name))
+    o += pck32(InLoadOrderModuleList_address + offset_name)
+
+    o += (offset_name - len(o)) * "B"
+    o += first_name
+    o += (0x1000 - len(o)) * "C"
+    for i, m in enumerate(modules_name):
+        # fname = os.path.join('win_dll', m)
+        if isinstance(m, tuple):
+            fname, e = m
+        else:
+            fname, e = m, None
+        bname = os.path.split(fname)[1].lower()
+        bname = "\x00".join(bname) + "\x00"
+        print hex(InLoadOrderModuleList_address + i * 0x1000)
+        if e is None:
+            e = pe_init.PE(open(fname, 'rb').read())
+
+        print "add module", hex(e.NThdr.ImageBase), repr(bname)
+
+        next_ad = InLoadOrderModuleList_address + (i + 1) * 0x1000
+        if i == len(modules_name) - 1:
+            next_ad = InLoadOrderModuleList_address
+        m_o = ""
+        m_o += pck32(next_ad)
+        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000)
+        m_o += pck32(next_ad + 8)
+        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 8)
+        m_o += pck32(next_ad + 0x10)
+        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 0x10)
+        m_o += pck32(e.NThdr.ImageBase)
+        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
+        m_o += pck32(e.NThdr.sizeofimage)
+
+        m_o += (0x24 - len(m_o)) * "A"
+        print hex(len(bname)), repr(bname)
+        m_o += struct.pack('HH', len(bname), len(bname) + 2)
+        m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name)
+
+        m_o += (0x2C - len(m_o)) * "A"
+        m_o += struct.pack('HH', len(bname), len(bname) + 2)
+        m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name)
+
+        m_o += (offset_name - len(m_o)) * "B"
+        m_o += bname
+        m_o += "\x00" * 3
+
+        m_o += (0x1000 - len(m_o)) * "J"
+
+        print "module", "%.8X" % e.NThdr.ImageBase, fname
+
+        o += m_o
+    return o
+
+
+all_seh_ad = dict([(x, None)
+                  for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD + 0x1000, 0x20)])
+# http://blog.fireeye.com/research/2010/08/download_exec_notes.html
+
+
+def init_seh(myjit):
+    global seh_count
+    seh_count = 0
+    # myjit.vm.vm_add_memory_page(tib_address, PAGE_READ | PAGE_WRITE,
+    # p(default_seh) + p(0) * 11 + p(peb_address))
+    myjit.vm.vm_add_memory_page(
+        FS_0_AD, PAGE_READ | PAGE_WRITE, build_fake_teb())
+    # myjit.vm.vm_add_memory_page(peb_address, PAGE_READ | PAGE_WRITE, p(0) *
+    # 3 + p(peb_ldr_data_address))
+    myjit.vm.vm_add_memory_page(
+        peb_address, PAGE_READ | PAGE_WRITE, build_fake_peb())
+    # myjit.vm.vm_add_memory_page(peb_ldr_data_address, PAGE_READ |
+    # PAGE_WRITE, p(0) * 3 + p(in_load_order_module_list_address) + p(0) *
+    # 0x20)
+
+    """
+    ldr_data += "\x00"*(InInitializationOrderModuleList_offset - len(ldr_data))
+    ldr_data += build_fake_InInitializationOrderModuleList(loaded_modules)
+    ldr_data += "\x00"*(InLoadOrderModuleList_offset - len(ldr_data))
+    ldr_data += build_fake_InLoadOrderModuleList(loaded_modules)
+    """
+    myjit.vm.vm_add_memory_page(
+        LDR_AD, PAGE_READ | PAGE_WRITE, "\x00" * MAX_MODULES * 0x1000)
+    module_info = create_modules_chain(myjit, loaded_modules)
+    fix_InLoadOrderModuleList(myjit, module_info)
+    fix_InMemoryOrderModuleList(myjit, module_info)
+    fix_InInitializationOrderModuleList(myjit, module_info)
+
+    ldr_data = build_fake_ldr_data(module_info)
+    myjit.vm.vm_set_mem(LDR_AD, ldr_data)
+    add_process_env(myjit)
+    add_process_parameters(myjit)
+
+    # myjit.vm.vm_add_memory_page(in_load_order_module_list_address,
+    #     PAGE_READ | PAGE_WRITE, p(0) * 40)
+    # myjit.vm.vm_add_memory_page(in_load_order_module_list_address,
+    #     PAGE_READ | PAGE_WRITE, build_fake_inordermodule(loaded_modules))
+    myjit.vm.vm_add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, pck32(
+        0xffffffff) + pck32(0x41414141) + pck32(0x42424242))
+
+    myjit.vm.vm_add_memory_page(
+        context_address, PAGE_READ | PAGE_WRITE, '\x00' * 0x2cc)
+    myjit.vm.vm_add_memory_page(
+        exception_record_address, PAGE_READ | PAGE_WRITE, '\x00' * 200)
+
+    myjit.vm.vm_add_memory_page(
+        FAKE_SEH_B_AD, PAGE_READ | PAGE_WRITE, 0x10000 * "\x00")
+
+# http://www.codeproject.com/KB/system/inject2exe.aspx#RestorethefirstRegistersContext5_1
+
+
+def regs2ctxt(regs):
+    ctxt = ""
+    ctxt += '\x00\x00\x00\x00'  # ContextFlags
+    ctxt += '\x00\x00\x00\x00' * 6  # drX
+    ctxt += '\x00' * 112  # float context
+    ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + \
+        '\x23\x00\x00\x00' + '\x23\x00\x00\x00'  # segment selectors
+    ctxt += pck32(regs['EDI']) + pck32(regs['ESI']) + pck32(regs['EBX']) + \
+        pck32(regs['EDX']) + pck32(regs['ECX']) + pck32(regs['EAX']) + \
+        pck32(regs['EBP']) + pck32(regs['EIP'])  # gpregs
+    ctxt += '\x23\x00\x00\x00'  # cs
+    ctxt += '\x00\x00\x00\x00'  # eflags
+    ctxt += pck32(regs['ESP'])  # esp
+    ctxt += '\x23\x00\x00\x00'  # ss segment selector
+    return ctxt
+
+
+def ctxt2regs(ctxt):
+    ctxt = ctxt[:]
+    regs = {}
+    # regs['ctxtsflags'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+    for i in xrange(8):
+        if i in [4, 5]:
+            continue
+        # regs['dr%d'%i] = upck32(ctxt[:4])
+        ctxt = ctxt[4:]
+
+    ctxt = ctxt[112:]  # skip float
+
+    # regs['seg_gs'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+    # regs['seg_fs'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+    # regs['seg_es'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+    # regs['seg_ds'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+
+    regs['EDI'], regs['ESI'], regs['EBX'], regs['EDX'], regs['ECX'], regs[
+        'EAX'], regs['EBP'], regs['EIP'] = struct.unpack('I' * 8, ctxt[:4 * 8])
+    ctxt = ctxt[4 * 8:]
+
+    # regs['seg_cs'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+
+    # regs['eflag'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+
+    regs['ESP'] = upck32(ctxt[:4])
+    ctxt = ctxt[4:]
+
+    for a, b in regs.items():
+        print a, hex(b)
+    # skip extended
+    return regs
+
+
+def get_free_seh_place():
+    global all_seh_ad
+    ads = all_seh_ad.keys()
+    ads.sort()
+    for ad in ads:
+        v = all_seh_ad[ad]
+        if v is None:
+            print 'TAKING SEH', hex(ad)
+            all_seh_ad[ad] = True
+            return ad
+    raise ValueError('too many stacked seh ')
+
+
+def free_seh_place(ad):
+    print 'RELEASING SEH', hex(ad)
+
+    if not ad in all_seh_ad:
+        raise ValueError('zarb seh ad!', hex(ad))
+    if all_seh_ad[ad] is not True:
+        # @wisk typolol
+        raise ValueError('seh alreaedy remouvede?!!', hex(ad))
+    all_seh_ad[ad] = None
+
+
+def fake_seh_handler(myjit, except_code):
+    global seh_count
+    regs = myjit.cpu.vm_get_gpreg()
+    print '-> exception at', hex(myjit.cpu.EIP), seh_count
+    seh_count += 1
+
+    # Help lambda
+    p = lambda s: struct.pack('I', s)
+
+    # dump_gpregs_py()
+    # jitarch.dump_gpregs()
+    # Forge a CONTEXT
+    ctxt = '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112
+    ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00'
+    ctxt += '\x23\x00\x00\x00'
+    ctxt += pck32(myjit.cpu.EDI) + pck32(myjit.cpu.ESI) + \
+            pck32(myjit.cpu.EBX) + pck32(myjit.cpu.EDX) + \
+            pck32(myjit.cpu.ECX) + pck32(myjit.cpu.EAX) + \
+            pck32(myjit.cpu.EBP) + pck32(myjit.cpu.EIP)
+    ctxt += '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + pck32(myjit.cpu.ESP)
+    ctxt += '\x23\x00\x00\x00'
+    # ctxt = regs2ctxt(regs)
+
+    # Find a room for seh
+    # seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000
+
+    # Get current seh (fs:[0])
+    seh_ptr = upck32(myjit.vm.vm_get_mem(tib_address, 4))
+
+    # Retrieve seh fields
+    old_seh, eh, safe_place = struct.unpack(
+        'III', myjit.vm.vm_get_mem(seh_ptr, 0xc))
+
+    print '-> seh_ptr', hex(seh_ptr), '-> { old_seh',
+    print hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}'
+    # print '-> write SEH at', hex(seh&0xffffffff)
+
+    # Write current seh
+    # myjit.vm.vm_add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) +
+    # p(eh) + p(safe_place) + p(0x99999999))
+
+    # Write context
+    myjit.vm.vm_set_mem(context_address, ctxt)
+
+    # Write exception_record
+
+    """
+    #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
+
+    typedef struct _EXCEPTION_RECORD {
+      DWORD                    ExceptionCode;
+      DWORD                    ExceptionFlags;
+      struct _EXCEPTION_RECORD *ExceptionRecord;
+      PVOID                    ExceptionAddress;
+      DWORD                    NumberParameters;
+      ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+    } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
+    """
+
+    myjit.vm.vm_set_mem(exception_record_address, pck32(except_code) +
+                        pck32(0) + pck32(0) + pck32(myjit.cpu.EIP) +
+                        pck32(0) + pck32(0))
+
+    # Prepare the stack
+    myjit.vm_push_uint32_t(context_address)               # Context
+    myjit.vm_push_uint32_t(seh_ptr)                       # SEH
+    myjit.vm_push_uint32_t(exception_record_address)      # ExceptRecords
+    myjit.vm_push_uint32_t(return_from_exception)         # Ret address
+
+    # Set fake new current seh for exception
+    fake_seh_ad = get_free_seh_place()
+    print hex(fake_seh_ad)
+    myjit.vm.vm_set_mem(fake_seh_ad, pck32(seh_ptr) + pck32(
+        0xaaaaaaaa) + pck32(0xaaaaaabb) + pck32(0xaaaaaacc))
+    myjit.vm.vm_set_mem(tib_address, pck32(fake_seh_ad))
+
+    dump_seh(myjit)
+
+    print '-> jumping at', hex(eh)
+    myjit.vm.vm_set_exception(0)
+    myjit.cpu.vm_set_exception(0)
+
+    # XXX set ebx to nul?
+    myjit.cpu.EBX = 0
+
+    return eh
+
+fake_seh_handler.base = FAKE_SEH_B_AD
+
+
+def dump_seh(myjit):
+    print 'dump_seh:'
+    print '-> tib_address:', hex(tib_address)
+    cur_seh_ptr = upck32(myjit.vm.vm_get_mem(tib_address, 4))
+    indent = 1
+    loop = 0
+    while True:
+        if loop > 5:
+            print "too many seh, quit"
+            return
+        prev_seh, eh = struct.unpack('II', myjit.vm.vm_get_mem(cur_seh_ptr, 8))
+        print '\t' * indent + 'seh_ptr:', hex(cur_seh_ptr),
+        print ' -> { prev_seh:', hex(prev_seh), 'eh:', hex(eh), '}'
+        if prev_seh in [0xFFFFFFFF, 0]:
+            break
+        cur_seh_ptr = prev_seh
+        indent += 1
+        loop += 1
+
+
+def set_win_fs_0(myjit, fs=4):
+    regs = myjit.cpu.vm_get_gpreg()
+    regs['FS'] = 0x4
+    myjit.cpu.vm_set_gpreg(regs)
+    myjit.cpu.vm_set_segm_base(regs['FS'], FS_0_AD)
+    segm_to_do = set([x86.regs.FS])
+    return segm_to_do
+
+
+def add_modules_info(pe_in, pe_in_name="toto.exe", all_pe=None):
+    global main_pe, main_pe_name, loaded_modules
+    if all_pe is None:
+        all_pe = []
+    main_pe = pe_in
+    main_pe_name = pe_in_name
+    loaded_modules = all_pe
+
+
+def return_from_seh(myjit):
+    "Handle return after a call to fake seh handler"
+
+    # Get current context
+    myjit.cpu.ESP = upck32(myjit.vm.vm_get_mem(context_address + 0xc4, 4))
+    logging.info('-> new esp: %x' % myjit.cpu.ESP)
+
+    # Rebuild SEH
+    old_seh = upck32(myjit.vm.vm_get_mem(tib_address, 4))
+    new_seh = upck32(myjit.vm.vm_get_mem(old_seh, 4))
+    logging.info('-> old seh: %x' % old_seh)
+    logging.info('-> new seh: %x' % new_seh)
+    myjit.vm.vm_set_mem(tib_address, pck32(new_seh))
+
+    dump_seh(myjit)
+
+    # Release SEH
+    free_seh_place(old_seh)
+
+    if myjit.cpu.EAX == 0x0:
+        # ExceptionContinueExecution
+        print '-> seh continues'
+        ctxt_ptr = context_address
+        print '-> context:', hex(ctxt_ptr)
+
+        # Get registers changes
+        ctxt_str = myjit.vm.vm_get_mem(ctxt_ptr, 0x2cc)
+        regs = ctxt2regs(ctxt_str)
+        myjit.pc = regs["EIP"]
+        for reg_name, reg_value in regs.items():
+            setattr(myjit.cpu, reg_name, reg_value)
+
+        logging.info('-> context::Eip: %x' % myjit.pc)
+
+    elif myjit.cpu.EAX == -1:
+        raise NotImplementedError("-> seh try to go to the next handler")
+
+    elif myjit.cpu.EAX == 1:
+        # ExceptionContinueSearch
+        raise NotImplementedError("-> seh, gameover")
diff --git a/miasm2/jitter/queue.h b/miasm2/jitter/queue.h
new file mode 100644
index 00000000..0caf72fb
--- /dev/null
+++ b/miasm2/jitter/queue.h
@@ -0,0 +1,553 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+//#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *				SLIST	LIST	STAILQ	TAILQ
+ * _HEAD			+	+	+	+
+ * _HEAD_INITIALIZER		+	+	+	+
+ * _ENTRY			+	+	+	+
+ * _INIT			+	+	+	+
+ * _EMPTY			+	+	+	+
+ * _FIRST			+	+	+	+
+ * _NEXT			+	+	+	+
+ * _PREV			-	-	-	+
+ * _LAST			-	-	+	+
+ * _FOREACH			+	+	+	+
+ * _FOREACH_SAFE		+	+	+	+
+ * _FOREACH_REVERSE		-	-	-	+
+ * _FOREACH_REVERSE_SAFE	-	-	-	+
+ * _INSERT_HEAD			+	+	+	+
+ * _INSERT_BEFORE		-	+	-	+
+ * _INSERT_AFTER		+	+	+	+
+ * _INSERT_TAIL			-	-	+	+
+ * _CONCAT			-	-	+	+
+ * _REMOVE_HEAD			+	-	+	-
+ * _REMOVE			+	+	+	+
+ *
+ */
+#define	QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+	char * lastfile;
+	int lastline;
+	char * prevfile;
+	int prevline;
+};
+
+#define	TRACEBUF	struct qm_trace trace;
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+
+#define	QMD_TRACE_HEAD(head) do {					\
+	(head)->trace.prevline = (head)->trace.lastline;		\
+	(head)->trace.prevfile = (head)->trace.lastfile;		\
+	(head)->trace.lastline = __LINE__;				\
+	(head)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#define	QMD_TRACE_ELEM(elem) do {					\
+	(elem)->trace.prevline = (elem)->trace.lastline;		\
+	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
+	(elem)->trace.lastline = __LINE__;				\
+	(elem)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#else
+#define	QMD_TRACE_ELEM(elem)
+#define	QMD_TRACE_HEAD(head)
+#define	TRACEBUF
+#define	TRASHIT(x)
+#endif	/* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != NULL;					\
+	    (varp) = &SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = SLIST_FIRST((head));		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_NEXT(curelm, field) =				\
+		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
+	}								\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (0)
+
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY((head)) ?						\
+		NULL :							\
+	        ((struct type *)					\
+		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = LIST_FIRST((head));				\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+		QMD_TRACE_HEAD(head);					\
+		QMD_TRACE_HEAD(head2);					\
+	}								\
+} while (0)
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else {								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	TRASHIT((elm)->field.tqe_next);					\
+	TRASHIT((elm)->field.tqe_prev);					\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+struct quehead {
+	struct quehead *qh_link;
+	struct quehead *qh_rlink;
+};
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+static __inline void
+insque(void *a, void *b)
+{
+	struct quehead *element = (struct quehead *)a,
+		 *head = (struct quehead *)b;
+
+	element->qh_link = head->qh_link;
+	element->qh_rlink = head;
+	head->qh_link = element;
+	element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+	struct quehead *element = (struct quehead *)a;
+
+	element->qh_link->qh_rlink = element->qh_rlink;
+	element->qh_rlink->qh_link = element->qh_link;
+	element->qh_rlink = 0;
+}
+
+#else /* !(__GNUC__ || __INTEL_COMPILER) */
+
+void	insque(void *a, void *b);
+void	remque(void *a);
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c
new file mode 100644
index 00000000..7d47fadc
--- /dev/null
+++ b/miasm2/jitter/vm_mngr.c
@@ -0,0 +1,1640 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "queue.h"
+#include "vm_mngr.h"
+
+
+
+
+/*
+struct memory_page_list_head memory_page_pool;
+struct code_bloc_list_head code_bloc_pool;
+
+struct memory_breakpoint_info_head memory_breakpoint_pool;
+*/
+
+/****************memory manager**************/
+
+
+
+
+#define MIN(a,b)  (((a)<(b))?(a):(b))
+#define MAX(a,b)  (((a)>(b))?(a):(b))
+
+
+//#define DEBUG_MIASM_AUTOMOD_CODE
+
+
+
+
+
+void print_val(uint64_t base, uint64_t addr)
+{
+	uint64_t *ptr =  (uint64_t *) addr;
+	fprintf(stderr, "addr 0x%"PRIX64" val 0x%"PRIX64"\n", addr-base, *ptr);
+}
+
+
+int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad)
+{
+	struct memory_page_node * mpn;
+	/*
+	mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT];
+	if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size))
+		return 1;
+	*/
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		if ((mpn->ad <= ad)  && (ad <mpn->ad + mpn->size))
+			return 1;
+	}
+
+	return 0;
+}
+
+
+/* return the address base of the memory page
+   containing addr
+*/
+uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t *addr_base)
+{
+	struct memory_page_node * mpn;
+	/*
+	mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT];
+	if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)){
+		*addr_base = mpn->ad;
+		return 1;
+	}
+	*/
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		if ((mpn->ad <= ad)  && (ad <mpn->ad + mpn->size)) {
+			*addr_base = mpn->ad;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint64_t ad)
+{
+	struct memory_page_node * mpn;
+#if 0
+	mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT];
+	if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size))
+		return mpn;
+
+	fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad);
+	//dump_memory_page_pool();
+	//dump_gpregs();
+	//exit(-1);
+	vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL;
+
+	return NULL;
+#else
+
+	//printf("search for page ad: %X\n", ad);
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		if ((mpn->ad <= ad) && (ad < mpn->ad + mpn->size))
+			return mpn;
+	}
+	fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad);
+	//dump_memory_page_pool();
+	//dump_gpregs();
+	//exit(-1);
+	vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL;
+	return NULL;
+#endif
+}
+
+
+
+
+static inline uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad)
+{
+	struct memory_page_node * mpn;
+	unsigned char * addr;
+	uint64_t ret = 0;
+	struct memory_breakpoint_info * b;
+
+
+	mpn = get_memory_page_from_address(vm_mngr, ad);
+	if (!mpn)
+		return 0;
+
+	if ((mpn->access & PAGE_READ) == 0){
+		fprintf(stderr, "access to non readable page!! %"PRIX64"\n", ad);
+		vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL;
+		return 0;
+	}
+
+	/* check read breakpoint*/
+	LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){
+		if ((b->access & BREAKPOINT_READ) == 0)
+			continue;
+		if ((b->ad <= ad) && (ad < b->ad + b->size))
+			vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN;
+	}
+
+
+	addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+
+	/* read fits in a page */
+	if (ad - mpn->ad + my_size/8 <= mpn->size){
+		switch(my_size){
+		case 8:
+			ret = *((unsigned char*)addr)&0xFF;
+			break;
+		case 16:
+			ret = *((unsigned short*)addr)&0xFFFF;
+			ret = Endian16_Swap(ret);
+			break;
+		case 32:
+			ret = *((unsigned int*)addr)&0xFFFFFFFF;
+			ret = Endian32_Swap(ret);
+			break;
+		case 64:
+			ret = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL;
+			ret = Endian64_Swap(ret);
+			break;
+		default:
+			exit(0);
+			break;
+		}
+	}
+	/* read is multiple page wide */
+	else{
+		unsigned int new_size = my_size;
+		int index = 0;
+		fprintf(stderr, "read multiple page! %"PRIX64" %d\n", ad, new_size);
+		dump_memory_page_pool(vm_mngr);
+		while (new_size){
+			mpn = get_memory_page_from_address(vm_mngr, ad);
+			if (!mpn)
+				return 0;
+			addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+			ret |= (*((unsigned char*)addr)&0xFF)<<(index);
+			index +=8;
+			new_size -= 8;
+			ad ++;
+		}
+		switch(my_size){
+		case 8:
+			ret = ret;
+			break;
+		case 16:
+			ret = Endian16_Swap(ret);
+			break;
+		case 32:
+			ret = Endian32_Swap(ret);
+			break;
+		case 64:
+			ret = Endian64_Swap(ret);
+			break;
+		default:
+			exit(0);
+			break;
+		}
+	}
+	return ret;
+}
+
+static inline void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size,
+				     uint64_t ad, uint64_t src)
+{
+	struct memory_page_node * mpn;
+	unsigned char * addr;
+	struct memory_breakpoint_info * b;
+
+	mpn = get_memory_page_from_address(vm_mngr, ad);
+	if (!mpn)
+		return;
+
+	if ((mpn->access & PAGE_WRITE) == 0){
+		fprintf(stderr, "access to non writable page!! %"PRIX64"\n", ad);
+		vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL;
+		return ;
+	}
+
+	/* check read breakpoint*/
+	LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){
+		if ((b->access & BREAKPOINT_WRITE) == 0)
+			continue;
+		if ((b->ad <= ad) && (ad < b->ad + b->size))
+			vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN;
+	}
+
+	addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+
+	/* write fits in a page */
+	if (ad - mpn->ad + my_size/8 <= mpn->size){
+		switch(my_size){
+		case 8:
+			*((unsigned char*)addr) = src&0xFF;
+			break;
+		case 16:
+			src = Endian16_Swap(src);
+			*((unsigned short*)addr) = src&0xFFFF;
+			break;
+		case 32:
+			src = Endian32_Swap(src);
+			*((unsigned int*)addr) = src&0xFFFFFFFF;
+			break;
+		case 64:
+			src = Endian64_Swap(src);
+			*((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL;
+			break;
+		default:
+			exit(0);
+			break;
+		}
+	}
+	/* write is multiple page wide */
+	else{
+		fprintf(stderr, "write multiple page! %"PRIX64" %d\n", ad, my_size);
+		dump_memory_page_pool(vm_mngr);
+		switch(my_size){
+
+		case 8:
+			src = src;
+			break;
+		case 16:
+			src = Endian16_Swap(src);
+			break;
+		case 32:
+			src = Endian32_Swap(src);
+			break;
+		case 64:
+			src = Endian64_Swap(src);
+			break;
+		default:
+			exit(0);
+			break;
+		}
+		while (my_size){
+			mpn = get_memory_page_from_address(vm_mngr, ad);
+			if (!mpn)
+				return;
+
+			addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+			*((unsigned char*)addr) = src&0xFF;
+			my_size -= 8;
+			src >>=8;
+			ad ++;
+		}
+	}
+}
+
+/* TODO: Those functions have to be moved to a common operations file, with
+ * parity, ...
+ */
+
+inline uint16_t bcdadd_16(uint16_t a, uint16_t b)
+{
+	int carry = 0;
+	int i,j = 0;
+	uint16_t res = 0;
+	int nib_a, nib_b;
+	for (i = 0; i < 16; i += 4) {
+		nib_a = (a  >> i) & (0xF);
+		nib_b = (b >> i) & (0xF);
+
+		j = (carry + nib_a + nib_b);
+		if (j >= 10) {
+			carry = 1;
+			j -= 10;
+			j &=0xf;
+		}
+		else {
+			carry = 0;
+		}
+		res += j << i;
+	}
+	return res;
+}
+
+inline uint16_t bcdadd_cf_16(uint16_t a, uint16_t b)
+{
+	int carry = 0;
+	int i,j = 0;
+	int nib_a, nib_b;
+	for (i = 0; i < 16; i += 4) {
+		nib_a = (a >> i) & (0xF);
+		nib_b = (b >> i) & (0xF);
+
+		j = (carry + nib_a + nib_b);
+		if (j >= 10) {
+			carry = 1;
+			j -= 10;
+			j &=0xf;
+		}
+		else {
+			carry = 0;
+		}
+	}
+	return carry;
+}
+// ##################
+
+void dump_code_bloc(vm_mngr_t* vm_mngr)
+{
+	struct code_bloc_node * cbp;
+	LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){
+		fprintf(stderr, "%"PRIX64"%"PRIX64"\n", cbp->ad_start,  cbp->ad_stop);
+	}
+
+}
+
+inline void check_write_code_bloc(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr)
+{
+	struct code_bloc_node * cbp;
+	vm_mngr->last_write_ad = addr;
+	vm_mngr->last_write_size = my_size;
+
+
+
+	//if(vmmngr.my_tick> my_tick)
+	//	printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src);
+	if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min ||
+	      addr >=vm_mngr->code_bloc_pool_ad_max)){
+		LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){
+			if ((cbp->ad_start < addr + my_size/8) &&
+			    (addr < cbp->ad_stop)){
+#ifdef DEBUG_MIASM_AUTOMOD_CODE
+				fprintf(stderr, "**********************************\n");
+				fprintf(stderr, "self modifying code %"PRIX64" %.8X\n",
+				       addr, my_size);
+				fprintf(stderr, "**********************************\n");
+				//dump_code_bloc(vm_mngr);
+#endif
+				vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD;
+
+				break;
+			}
+		}
+	}
+}
+
+PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+	PyObject* pyaddr;
+	PyObject* b;
+
+	//printf("addr2blocobj %"PRIx64"\n", addr);
+	pyaddr = PyLong_FromUnsignedLongLong(addr);
+	/*
+	Py_INCREF(pyaddr);
+	return pyaddr;
+	*/
+	b = PyDict_GetItem(vm_mngr->addr2obj, pyaddr);
+	if (b == NULL) {
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+
+	//printf("addr2blocobj OBJ %p\n", b);
+	Py_INCREF(b);
+	return b;
+}
+
+/*
+PyObject* add_code_resolver(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+	pyaddr = PyLong_FromUnsignedLongLong(addr);
+
+	func_resolver* f = malloc(sizeof(func_resolver));
+	f->func = addr2blocobj;
+	fsdfsd
+	return f;
+}
+*/
+/*
+void MEM_WRITE(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr, unsigned int src)
+{
+	struct code_bloc_node * cbp;
+
+	vm_mngr->last_write_ad = addr;
+	vm_mngr->last_write_size = my_size;
+
+	//if(vmmngr.my_tick> my_tick)
+	//	printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src);
+	if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min ||
+	      addr >= vm_mngr->code_bloc_pool_ad_max)){
+		LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){
+			if ((cbp->ad_start <= addr + my_size/8) &&
+			    (addr < cbp->ad_stop)){
+#ifdef DEBUG_MIASM_AUTOMOD_CODE
+				fprintf(stderr, "self modifying code %"PRIX64" %.8X\n",
+				       addr, my_size);
+#endif
+				vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD;
+				break;
+			}
+		}
+	}
+
+	memory_page_write(vm_mngr, my_size, addr, src);
+}
+*/
+void MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src)
+{
+	check_write_code_bloc(vm_mngr, 8, addr);
+	memory_page_write(vm_mngr, 8, addr, src);
+}
+
+void MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src)
+{
+	check_write_code_bloc(vm_mngr, 16, addr);
+	memory_page_write(vm_mngr, 16, addr, src);
+}
+void MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src)
+{
+	check_write_code_bloc(vm_mngr, 32, addr);
+	memory_page_write(vm_mngr, 32, addr, src);
+}
+void MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src)
+{
+	check_write_code_bloc(vm_mngr, 64, addr);
+	memory_page_write(vm_mngr, 64, addr, src);
+}
+
+unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr)
+{
+    unsigned int ret;
+    ret = memory_page_read(vm_mngr, my_size, addr);
+    return ret;
+}
+
+unsigned char MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+    unsigned char ret;
+    ret = memory_page_read(vm_mngr, 8, addr);
+    return ret;
+}
+unsigned short MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+    unsigned short ret;
+    ret = memory_page_read(vm_mngr, 16, addr);
+    return ret;
+}
+unsigned int MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+    unsigned int ret;
+    ret = memory_page_read(vm_mngr, 32, addr);
+    return ret;
+}
+uint64_t MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr)
+{
+    uint64_t ret;
+    ret = memory_page_read(vm_mngr, 64, addr);
+    return ret;
+}
+
+inline unsigned int parity(unsigned int a)
+{
+#if defined(__builtin_parity)
+	return __builtin_parity(a);
+#else
+    unsigned int tmp, cpt;
+
+    tmp = a&0xFF;
+    cpt = 1;
+    while (tmp!=0){
+	    cpt^=tmp&1;
+	    tmp>>=1;
+    }
+    return cpt;
+#endif
+}
+
+
+int shift_right_arith(unsigned int size, int a, unsigned int b)
+{
+    int i32_a;
+    short i16_a;
+    char i8_a;
+    switch(size){
+	    case 8:
+		    i8_a = a;
+		    return (i8_a >> b)&0xff;
+	    case 16:
+		    i16_a = a;
+		    return (i16_a >> b)&0xffff;
+	    case 32:
+		    i32_a = a;
+		    return (i32_a >> b)&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in shift %d\n", size);
+		    exit(0);
+    }
+}
+/*
+int shift_right_arith_08(int a, unsigned int b)
+{
+	char i8_a;
+	i8_a = a;
+	return (i8_a >> b)&0xff;
+}
+
+int shift_right_arith_16(int a, unsigned int b)
+{
+	short i16_a;
+	i16_a = a;
+	return (i16_a >> b)&0xffff;
+}
+
+int shift_right_arith_32(int a, unsigned int b)
+{
+	int i32_a;
+	i32_a = a;
+	return (i32_a >> b)&0xffffffff;
+}
+*/
+unsigned int shift_right_logic(unsigned int size,
+			       unsigned int a, unsigned int b)
+{
+    unsigned int u32_a;
+    unsigned short u16_a;
+    unsigned char u8_a;
+    switch(size){
+	    case 8:
+		    u8_a = a;
+		    return (u8_a >> b)&0xff;
+	    case 16:
+		    u16_a = a;
+		    return (u16_a >> b)&0xffff;
+	    case 32:
+		    u32_a = a;
+		    return (u32_a >> b)&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in shift %d\n", size);
+		    exit(0);
+    }
+}
+/*
+int shift_right_logic_08(unsigned int a, unsigned int b)
+{
+	unsigned char u8_a;
+	u8_a = a;
+	return (u8_a >> b)&0xff;
+}
+
+int shift_right_logic_16(unsigned int a, unsigned int b)
+{
+	unsigned short u16_a;
+	u16_a = a;
+	return (u16_a >> b)&0xffff;
+}
+
+int shift_right_logic_32(unsigned int a, unsigned int b)
+{
+	unsigned int u32_a;
+	u32_a = a;
+	return (u32_a >> b)&0xffffffff;
+}
+*/
+int shift_left_logic(unsigned int size, unsigned int a, unsigned int b)
+{
+    switch(size){
+	    case 8:
+		    return (a<<b)&0xff;
+	    case 16:
+		    return (a<<b)&0xffff;
+	    case 32:
+		    return (a<<b)&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in shift %d\n", size);
+		    exit(0);
+    }
+}
+/*
+int shift_left_logic_O8(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xff;
+}
+
+int shift_left_logic_16(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xffff;
+}
+
+int shift_left_logic_32(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xffffffff;
+}
+*/
+
+unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b)
+{
+	unsigned int mask;
+
+	switch (size) {
+		case 8: mask = 0xff; break;
+		case 16: mask = 0xffff; break;
+		case 32: mask = 0xffffffff; break;
+		default: fprintf(stderr, "inv size in mul %d\n", size); exit(0);
+	}
+
+	a &= mask;
+	b &= mask;
+	return ((int64_t)a * (int64_t) b) & mask;
+}
+
+unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b)
+{
+	uint64_t res = 0;
+	unsigned int mask;
+
+	switch (size) {
+		case 8: mask = 0xff; break;
+		case 16: mask = 0xffff; break;
+		case 32: mask = 0xffffffff; break;
+		default: fprintf(stderr, "inv size in mul %d\n", size); exit(0);
+	}
+
+	a &= mask;
+	b &= mask;
+	res = ((uint64_t)a * (uint64_t)b);
+	return (res >> 32) & mask;
+}
+
+
+unsigned int imul_lo_op_08(char a, char b)
+{
+	return a*b;
+}
+
+unsigned int imul_lo_op_16(short a, short b)
+{
+	return a*b;
+}
+
+unsigned int imul_lo_op_32(int a, int b)
+{
+	return a*b;
+}
+
+int imul_hi_op_08(char a, char b)
+{
+	int64_t res = 0;
+	res = a*b;
+	return res>>8;
+}
+
+int imul_hi_op_16(short a, short b)
+{
+	int64_t res = 0;
+	res = a*b;
+	return res>>16;
+}
+
+int imul_hi_op_32(int a, int b)
+{
+	int64_t res = 0;
+	res = (int64_t)a*(int64_t)b;
+	//printf("%x %x dd %"PRIx64"\n", a, b, res);
+	return res>>32ULL;
+}
+
+unsigned int umul16_lo(unsigned short a, unsigned short b)
+{
+	return (a*b) & 0xffff;
+}
+
+unsigned int umul16_hi(unsigned short a, unsigned short b)
+{
+	uint32_t c;
+	c = a*b;
+	return (c>>16) & 0xffff;
+}
+
+
+
+
+unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c)
+{
+    int64_t num;
+    if (c == 0)
+    {
+	    //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO;
+	    return 0;
+    }
+    num = ((int64_t)a << size) + b;
+    num/=(int64_t)c;
+    return num;
+}
+
+
+unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c)
+{
+    int64_t num;
+
+    if (c == 0)
+    {
+	    //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO;
+	    return 0;
+    }
+
+    num = ((int64_t)a << size) + b;
+    num = (int64_t)num-c*(num/c);
+    return num;
+}
+
+
+unsigned int rot_left(unsigned int size, unsigned int a, unsigned int b)
+{
+    unsigned int tmp;
+
+    b = b&0x1F;
+    b %= size;
+    switch(size){
+	    case 8:
+		    tmp = (a << b) | ((a&0xFF) >> (size-b));
+		    return tmp&0xff;
+	    case 16:
+		    tmp = (a << b) | ((a&0xFFFF) >> (size-b));
+		    return tmp&0xffff;
+	    case 32:
+		    tmp = (a << b) | ((a&0xFFFFFFFF) >> (size-b));
+		    return tmp&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in rotleft %d\n", size);
+		    exit(0);
+    }
+}
+
+unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b)
+{
+    unsigned int tmp;
+
+    b = b&0x1F;
+    b %= size;
+    switch(size){
+	    case 8:
+		    tmp = ((a&0xFF) >> b) | (a << (size-b));
+		    return tmp&0xff;
+	    case 16:
+		    tmp = ((a&0xFFFF) >> b) | (a << (size-b));
+		    return tmp&0xffff;
+	    case 32:
+		    tmp = ((a&0xFFFFFFFF) >> b) | (a << (size-b));
+		    return tmp&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in rotleft %d\n", size);
+		    exit(0);
+    }
+}
+
+
+int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+    uint64_t tmp;
+
+
+    size++;
+    b %= size;
+
+    if (b == 0) {
+	    switch(size){
+		    case 8+1:
+			    return a&0xff;
+		    case 16+1:
+			    return a&0xffff;
+		    case 32+1:
+			    return a&0xffffffff;
+		    default:
+			    fprintf(stderr, "inv size in rclleft %d\n", size);
+			    exit(0);
+	    }
+    }
+
+    tmp = (a<<1) | cf;
+    b -=1;
+    switch(size){
+	    case 8+1:
+		    tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b));
+		    return tmp&0xff;
+	    case 16+1:
+		    tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b));
+		    return tmp&0xffff;
+	    case 32+1:
+		    tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b));
+		    return tmp&0xffffffff;
+	    default:
+		    fprintf(stderr, "inv size in rclleft %d\n", size);
+		    exit(0);
+    }
+}
+
+int rcr_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+	return rcl_rez_op(size, a, size+1-b, cf);
+
+}
+
+
+int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+    uint64_t tmp;
+
+    tmp = (cf<< size) | a;
+
+    size++;
+    b %= size;
+
+    switch(size){
+	    case 8+1:
+		    tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b));
+		    return (tmp>>8)&1;
+	    case 16+1:
+		    tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b));
+		    return (tmp>>16)&1;
+	    case 32+1:
+		    tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b));
+		    return (tmp>>32)&1;
+	    default:
+		    fprintf(stderr, "inv size in rclleft %d\n", size);
+		    exit(0);
+    }
+}
+
+int rcr_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+	return rcl_cf_op(size, a, size+1-b, cf);
+}
+unsigned int my_bsr(unsigned int a, unsigned int b)
+{
+	int i;
+
+	for (i=31; i>=0; i--){
+		if (b & (1<<i))
+			return i;
+	}
+	return a;
+}
+
+unsigned int my_bsf(unsigned int a, unsigned int b)
+{
+	int i;
+
+	for (i=0; i<32; i++){
+		if (b & (1<<i))
+			return i;
+	}
+	return a;
+}
+
+
+unsigned int my_imul08(unsigned int a, unsigned int b)
+{
+	char a08, b08;
+	short a16;
+
+	a08 = a&0xFF;
+	b08 = b&0xFF;
+	a16 = a08*b08;
+	return (int)a16;
+}
+
+
+
+unsigned int cpuid(unsigned int a, unsigned int reg_num)
+{
+	if (reg_num >3){
+		fprintf(stderr, "not implemented cpuid reg %x\n", reg_num);
+		exit(-1);
+	}
+
+	if (a == 0){
+		switch(reg_num){
+		case 0:
+			return 0xa;
+		case 1:
+			return 0x756E6547;
+		case 2:
+			return 0x6C65746E;
+		case 3:
+			return 0x49656E69;
+		}
+	}
+
+	else if (a == 1){
+		switch(reg_num){
+		case 0:
+			//return 0x000006FB;
+			return 0x00020652;
+		case 1:
+			//return 0x02040800;
+			return 0x00000800;
+		case 2:
+			//return 0x0004E3BD;
+			return 0x00000209;
+		case 3:
+			//return 0xBFEBFBFF;
+			return 0x078bf9ff;
+		}
+	}
+	else{
+		fprintf(stderr, "WARNING not implemented cpuid index %X!\n", a);
+		//exit(-1);
+	}
+	return 0;
+}
+
+#define DEBUG_MIASM_DOUBLE
+
+void dump_float(void)
+{
+	/*
+	printf("%e\n", vmmngr.float_st0);
+	printf("%e\n", vmmngr.float_st1);
+	printf("%e\n", vmmngr.float_st2);
+	printf("%e\n", vmmngr.float_st3);
+	printf("%e\n", vmmngr.float_st4);
+	printf("%e\n", vmmngr.float_st5);
+	printf("%e\n", vmmngr.float_st6);
+	printf("%e\n", vmmngr.float_st7);
+	*/
+}
+
+double mem_32_to_double(unsigned int m)
+{
+	float f;
+	double d;
+
+	f = *((float*)&m);
+	d = f;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%d float %e\n", m, d);
+#endif
+	return d;
+}
+
+
+double mem_64_to_double(uint64_t m)
+{
+	double d;
+	d = *((double*)&m);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%"PRId64" double %e\n", m, d);
+#endif
+	return d;
+}
+
+double int_16_to_double(unsigned int m)
+{
+	double d;
+
+	d = (double)(m&0xffff);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%d double %e\n", m, d);
+#endif
+	return d;
+}
+
+double int_32_to_double(unsigned int m)
+{
+	double d;
+
+	d = (double)m;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%d double %e\n", m, d);
+#endif
+	return d;
+}
+
+double int_64_to_double(uint64_t m)
+{
+	double d;
+
+	d = (double)m;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%"PRId64" double %e\n", m, d);
+#endif
+	return d;
+}
+
+int32_t double_to_int_32(double d)
+{
+	int32_t i;
+
+	i = (int32_t)d;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e int %d\n", d, i);
+#endif
+	return i;
+}
+
+int64_t double_to_int_64(double d)
+{
+	int64_t i;
+
+	i = (int64_t)d;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e int %"PRId64"\n", d, i);
+#endif
+	return i;
+}
+
+
+double fadd(double a, double b)
+{
+	double c;
+	c = a + b;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e + %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+double fsub(double a, double b)
+{
+	double c;
+	c = a - b;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e - %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+double fmul(double a, double b)
+{
+	double c;
+	c = a * b;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e * %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+double fdiv(double a, double b)
+{
+	double c;
+	c = a / b;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e / %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+double ftan(double a)
+{
+	double b;
+	b = tan(a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e tan %e\n", a, b);
+#endif
+	return b;
+}
+
+double frndint(double a)
+{
+	int64_t b;
+	double c;
+	b = (int64_t)a;
+	c = (double)b;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e double %e\n", a, c);
+#endif
+	return c;
+}
+
+double fsin(double a)
+{
+	double b;
+	b = sin(a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e sin %e\n", a, b);
+#endif
+	return b;
+}
+
+double fcos(double a)
+{
+	double b;
+	b = cos(a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e cos %e\n", a, b);
+#endif
+	return b;
+}
+
+
+double fscale(double a, double b)
+{
+	double c;
+	c = a * exp2(trunc(b));
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e *exp2 %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+double f2xm1(double a)
+{
+	double b;
+	b = exp2(a)-1;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e exp2 -1 %e\n", a, b);
+#endif
+	return b;
+}
+
+double fsqrt(double a)
+{
+	double b;
+	b = sqrt(a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e sqrt %e\n", a, b);
+#endif
+	return b;
+}
+
+double fabs(double a)
+{
+	double b;
+	b = abs(a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e abs %e\n", a, b);
+#endif
+	return b;
+}
+
+
+
+unsigned int fcom_c0(double a, double b)
+{
+	if (a>=b)
+		return 0;
+	return 1;
+}
+unsigned int fcom_c1(double a, double b)
+{
+	//XXX
+	return 0;
+}
+unsigned int fcom_c2(double a, double b)
+{
+	return 0;
+}
+unsigned int fcom_c3(double a, double b)
+{
+	if (a==b)
+		return 1;
+	return 0;
+}
+
+
+unsigned int double_to_mem_32(double d)
+{
+	unsigned int m;
+	float f;
+	f = d;
+	m = *((unsigned int*)&f);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%d %e\n", m, d);
+#endif
+	return m;
+}
+
+uint64_t double_to_mem_64(double d)
+{
+	uint64_t m;
+	m = *((uint64_t*)&d);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%"PRId64" %e\n", m, d);
+#endif
+	return m;
+}
+
+struct memory_page_node * create_memory_page_node(uint64_t ad, unsigned int size, unsigned int access)
+{
+	struct memory_page_node * mpn;
+	void* p;
+
+	mpn = malloc(sizeof(*mpn));
+	if (!mpn){
+		fprintf(stderr, "cannot alloc mpn\n");
+		return NULL;
+	}
+	p = malloc(size);
+	if (!p){
+		fprintf(stderr, "cannot alloc %d\n", size);
+		return NULL;
+	}
+	mpn->ad = ad;
+	mpn->size = size;
+	mpn->access = access;
+	mpn->ad_hp = p;
+
+	return mpn;
+}
+
+
+struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop)
+{
+	struct code_bloc_node * cbp;
+
+	cbp = malloc(sizeof(*cbp));
+	if (!cbp){
+		fprintf(stderr, "cannot alloc cbp\n");
+		exit(-1);
+	}
+
+	cbp->ad_start = ad_start;
+	cbp->ad_stop = ad_stop;
+
+	return cbp;
+}
+
+
+void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp)
+{
+	LIST_INSERT_HEAD(&vm_mngr->code_bloc_pool, cbp, next);
+	if (vm_mngr->code_bloc_pool_ad_min> cbp->ad_start)
+		vm_mngr->code_bloc_pool_ad_min = cbp->ad_start;
+	if (vm_mngr->code_bloc_pool_ad_max< cbp->ad_stop)
+		vm_mngr->code_bloc_pool_ad_max = cbp->ad_stop;
+}
+
+void dump_code_bloc_pool(vm_mngr_t* vm_mngr)
+{
+	struct code_bloc_node * cbp;
+
+	LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){
+		printf("ad start %"PRIX64" ad_stop %"PRIX64"\n",
+		       cbp->ad_start,
+		       cbp->ad_stop);
+	}
+}
+
+
+void init_memory_page_pool(vm_mngr_t* vm_mngr)
+{
+	unsigned int i;
+	LIST_INIT(&vm_mngr->memory_page_pool);
+	for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++)
+		vm_mngr->memory_page_pool_tab[i] = NULL;
+}
+
+void init_code_bloc_pool(vm_mngr_t* vm_mngr)
+{
+	LIST_INIT(&vm_mngr->code_bloc_pool);
+	vm_mngr->code_bloc_pool_ad_min = 0xffffffff;
+	vm_mngr->code_bloc_pool_ad_max = 0;
+}
+
+void init_memory_breakpoint(vm_mngr_t* vm_mngr)
+{
+	LIST_INIT(&vm_mngr->memory_breakpoint_pool);
+}
+
+
+void reset_memory_page_pool(vm_mngr_t* vm_mngr)
+{
+	struct memory_page_node * mpn;
+	unsigned int i;
+
+	while (!LIST_EMPTY(&vm_mngr->memory_page_pool)) {
+		mpn = LIST_FIRST(&vm_mngr->memory_page_pool);
+		LIST_REMOVE(mpn, next);
+		free(mpn->ad_hp);
+		free(mpn);
+	}
+	for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++)
+		vm_mngr->memory_page_pool_tab[i] = NULL;
+
+}
+
+
+void reset_code_bloc_pool(vm_mngr_t* vm_mngr)
+{
+	struct code_bloc_node * cbp;
+
+
+	while (!LIST_EMPTY(&vm_mngr->code_bloc_pool)) {
+		cbp = LIST_FIRST(&vm_mngr->code_bloc_pool);
+		LIST_REMOVE(cbp, next);
+		free(cbp);
+	}
+	vm_mngr->code_bloc_pool_ad_min = 0xffffffff;
+	vm_mngr->code_bloc_pool_ad_max = 0;
+}
+
+
+void reset_memory_breakpoint(vm_mngr_t* vm_mngr)
+{
+	struct memory_breakpoint_info * mpn;
+
+	while (!LIST_EMPTY(&vm_mngr->memory_breakpoint_pool)) {
+		mpn = LIST_FIRST(&vm_mngr->memory_breakpoint_pool);
+		LIST_REMOVE(mpn, next);
+		free(mpn);
+	}
+
+}
+
+
+int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a)
+{
+	struct memory_page_node * mpn;
+
+	/*
+	for (i=mpn_a->ad >> MEMORY_PAGE_POOL_MASK_BIT;
+	     i<(mpn_a->ad + mpn_a->size + PAGE_SIZE - 1)>>MEMORY_PAGE_POOL_MASK_BIT;
+	     i++){
+		if (memory_page_pool_tab[i] !=NULL){
+			return 1;
+		}
+	}
+	*/
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		if (mpn->ad >= mpn_a->ad + mpn_a->size)
+			continue;
+		if (mpn->ad + mpn->size  <= mpn_a->ad)
+			continue;
+		printf("is mpn in! %"PRIX64" %"PRIX64" \n", mpn_a->ad, mpn_a->size);
+		printf("known:! %"PRIX64" %"PRIX64" \n", mpn->ad, mpn->size);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+void insert_mpn_in_tab(struct memory_page_node* mpn_a)
+{
+	/*
+	for (i=mpn_a->ad >> MEMORY_PAGE_POOL_MASK_BIT;
+	     i<(mpn_a->ad + mpn_a->size + PAGE_SIZE - 1)>>MEMORY_PAGE_POOL_MASK_BIT;
+	     i++){
+		if (memory_page_pool_tab[i] !=NULL){
+			fprintf(stderr, "known page in tab\n");
+			exit(1);
+		}
+		memory_page_pool_tab[i] = mpn_a;
+	}
+	*/
+
+}
+
+void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a)
+{
+	struct memory_page_node * mpn;
+	struct memory_page_node * lmpn;
+
+	if (LIST_EMPTY(&vm_mngr->memory_page_pool)){
+		LIST_INSERT_HEAD(&vm_mngr->memory_page_pool, mpn_a, next);
+		insert_mpn_in_tab(mpn_a);
+		return;
+	}
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		lmpn = mpn;
+		if (mpn->ad < mpn_a->ad)
+			continue;
+		LIST_INSERT_BEFORE(mpn, mpn_a, next);
+		insert_mpn_in_tab(mpn_a);
+		return;
+	}
+	LIST_INSERT_AFTER(lmpn, mpn_a, next);
+	insert_mpn_in_tab(mpn_a);
+
+}
+
+void dump_memory_page_pool(vm_mngr_t* vm_mngr)
+{
+	struct memory_page_node * mpn;
+
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		printf("ad %"PRIX64" size %"PRIX64" %c%c%c hpad %p\n",
+		       mpn->ad,
+		       mpn->size,
+		       mpn->access & PAGE_READ? 'R':'_',
+		       mpn->access & PAGE_WRITE? 'W':'_',
+		       mpn->access & PAGE_EXEC? 'X':'_',
+		       mpn->ad_hp
+		       );
+	}
+}
+
+void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr)
+{
+	struct memory_breakpoint_info * mpn;
+
+	LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){
+		printf("ad %"PRIX64" size %"PRIX64" access %"PRIX64"\n",
+		       mpn->ad,
+		       mpn->size,
+		       mpn->access
+		       );
+	}
+}
+
+
+void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access)
+{
+	struct memory_breakpoint_info * mpn_a;
+	mpn_a = malloc(sizeof(*mpn_a));
+	if (!mpn_a) {
+		printf("cannot alloc\n");
+		exit(0);
+	}
+	mpn_a->ad = ad;
+	mpn_a->size = size;
+	mpn_a->access = access;
+
+	LIST_INSERT_HEAD(&vm_mngr->memory_breakpoint_pool, mpn_a, next);
+
+}
+
+void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access)
+{
+	struct memory_breakpoint_info * mpn;
+
+	LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){
+		if (mpn->ad == ad && mpn->access == access)
+			LIST_REMOVE(mpn, next);
+	}
+
+}
+
+
+
+
+
+
+
+unsigned int get_memory_page_next(vm_mngr_t* vm_mngr, unsigned int n_ad)
+{
+	struct memory_page_node * mpn;
+	uint64_t ad = 0;
+
+	LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){
+		if (mpn->ad < n_ad)
+			continue;
+
+		if (ad == 0 || mpn->ad <ad)
+			ad = mpn->ad;
+	}
+	return ad;
+}
+
+
+#if 0
+unsigned int get_memory_page_from_min_ad(unsigned int size)
+{
+	struct memory_page_node * mpn;
+	unsigned int c_ad ;
+	unsigned int min_ad = min_page_ad;
+	int end = 0;
+	/* first, find free min ad */
+	while (!end){
+		end = 1;
+		LIST_FOREACH(mpn, &memory_page_pool, next){
+			c_ad = (mpn->ad + mpn->size+0x1000)&0xfffff000;
+			if (c_ad <= min_ad)
+				continue;
+			if (mpn->ad <= min_ad){
+				min_ad = c_ad;
+				end = 0;
+				break;
+			}
+			if (mpn->ad - min_ad < size){
+				min_ad = c_ad;
+				end = 0;
+				break;
+			}
+		}
+	}
+	return min_ad;
+ }
+#endif
+
+
+
+/********************************************/
+
+void hexdump(char* m, unsigned int l)
+{
+  int i, j, last;
+  last = 0;
+  for (i=0;i<l;i++){
+      if (!(i%0x10) && i){
+      last = i;
+      printf("    ");
+      for (j=-0x10;j<0;j++){
+	      if (isprint(m[i+j])){
+		      printf("%c", m[i+j]);
+	      }
+	      else{
+		      printf(".");
+	      }
+      }
+      printf("\n");
+      }
+      printf("%.2X ", m[i]&0xFF);
+  }
+  l-=last;
+  if (l){
+    for (j=i;j<last+0x10;j++)
+      printf("   ");
+    printf("    ");
+    for (j = 0;l;j++){
+      if (isprint(m[last+j])){
+	      printf("%c", m[last+j]);
+      }
+      else{
+	      printf(".");
+      }
+      l--;
+    }
+  }
+  printf("\n");
+
+}
+
+
+
+
+unsigned int access_segment(unsigned int d)
+{
+	// XXX TODO
+	printf("access segment %X\n", d);
+	return 0;
+}
+unsigned int access_segment_ok(unsigned int d)
+{
+	// XXX TODO
+	printf("access segment ok %X\n", d);
+	return 0;
+}
+
+unsigned int load_segment_limit(unsigned int d)
+{
+	// XXX TODO
+	printf("load segment limit %X\n", d);
+	return 0;
+}
+unsigned int load_segment_limit_ok(unsigned int d)
+{
+	// XXX TODO
+	printf("load segment limit ok %X\n", d);
+	return 0;
+}
+
+unsigned int load_tr_segment_selector(unsigned int d)
+{
+	// XXX TODO
+	return 0;
+}
+
+// Return vm_mngr's exception flag value
+uint64_t get_exception_flag(vm_mngr_t* vm_mngr)
+{
+	return vm_mngr->exception_flags;
+}
diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h
new file mode 100644
index 00000000..1e032200
--- /dev/null
+++ b/miasm2/jitter/vm_mngr.h
@@ -0,0 +1,363 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef CODENAT_H
+#define CODENAT_H
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define Endian16_Swap(value) \
+      ((((uint16_t)((value) & 0x00FF)) << 8) | \
+       (((uint16_t)((value) & 0xFF00)) >> 8))
+
+#define Endian32_Swap(value) \
+	((((uint32_t)((value) & 0x000000FF)) << 24) |	\
+	 (((uint32_t)((value) & 0x0000FF00)) << 8) |	\
+	 (((uint32_t)((value) & 0x00FF0000)) >> 8) |	\
+	 (((uint32_t)((value) & 0xFF000000)) >> 24))
+
+#define Endian64_Swap(value)					      \
+	(((((uint64_t)value)<<56) & 0xFF00000000000000ULL)  |	      \
+	 ((((uint64_t)value)<<40) & 0x00FF000000000000ULL)  |	      \
+	 ((((uint64_t)value)<<24) & 0x0000FF0000000000ULL)  |	      \
+	 ((((uint64_t)value)<< 8) & 0x000000FF00000000ULL)  |	      \
+	 ((((uint64_t)value)>> 8) & 0x00000000FF000000ULL)  |	      \
+	 ((((uint64_t)value)>>24) & 0x0000000000FF0000ULL)  |	      \
+	 ((((uint64_t)value)>>40) & 0x000000000000FF00ULL)  |	      \
+	 ((((uint64_t)value)>>56) & 0x00000000000000FFULL))
+#else
+#define Endian16_Swap(value) (value)
+
+#define Endian32_Swap(value) (value)
+
+#define Endian64_Swap(value) (value)
+#endif
+
+
+
+
+LIST_HEAD(memory_page_list_head, memory_page_node);
+LIST_HEAD(code_bloc_list_head, code_bloc_node);
+LIST_HEAD(memory_breakpoint_info_head, memory_breakpoint_info);
+
+
+#define BREAKPOINT_READ 1
+#define BREAKPOINT_WRITE 2
+
+
+
+#define MAX_MEMORY_PAGE_POOL_TAB 0x100000
+#define MEMORY_PAGE_POOL_MASK_BIT 12
+#define PAGE_SIZE (1<<MEMORY_PAGE_POOL_MASK_BIT)
+
+typedef struct {
+
+	struct memory_page_list_head memory_page_pool;
+	struct code_bloc_list_head code_bloc_pool;
+	struct memory_breakpoint_info_head memory_breakpoint_pool;
+
+	struct memory_page_node *memory_page_pool_tab[MAX_MEMORY_PAGE_POOL_TAB];
+
+	unsigned int *code_addr_tab;
+	unsigned int code_bloc_pool_ad_min;
+	unsigned int code_bloc_pool_ad_max;
+
+	uint64_t exception_flags;
+	uint64_t exception_flags_new;
+	uint64_t last_write_ad;
+	uint64_t last_write_size ;
+	PyObject *cb_automod;
+	PyObject *addr2obj;
+}vm_mngr_t;
+
+
+
+typedef struct {
+	PyObject *func;
+}func_resolver;
+
+
+
+
+//extern vm_mngr_t vmmngr;
+
+struct memory_page_node {
+	uint64_t ad;
+	uint64_t size;
+	uint64_t access;
+	void* ad_hp;
+	LIST_ENTRY(memory_page_node)   next;
+};
+
+
+
+struct code_bloc_node {
+	uint64_t ad_start;
+	uint64_t ad_stop;
+	uint64_t ad_code;
+	LIST_ENTRY(code_bloc_node)   next;
+};
+
+
+struct memory_breakpoint_info {
+	uint64_t ad;
+	uint64_t size;
+	uint64_t access;
+	LIST_ENTRY(memory_breakpoint_info)   next;
+};
+
+
+#define PAGE_READ 1
+#define PAGE_WRITE 2
+#define PAGE_EXEC 4
+
+#define EXCEPT_DO_NOT_UPDATE_PC (1<<25)
+
+// interrupt with eip update after instr
+#define EXCEPT_CODE_AUTOMOD (1<<0)
+#define EXCEPT_SOFT_BP (1<<1)
+#define EXCEPT_INT_XX (1<<2)
+
+#define EXCEPT_BREAKPOINT_INTERN (1<<10)
+
+#define EXCEPT_NUM_UPDT_EIP (1<<11)
+// interrupt with eip at instr
+#define EXCEPT_UNK_MEM_AD ((1<<12) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_THROW_SEH ((1<<13) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_UNK_EIP ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_ACCESS_VIOL ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_INT_DIV_BY_ZERO ((1<<16) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_PRIV_INSN ((1<<17) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_ILLEGAL_INSN ((1<<18) | EXCEPT_DO_NOT_UPDATE_PC)
+#define EXCEPT_UNK_MNEMO ((1<<19) | EXCEPT_DO_NOT_UPDATE_PC)
+
+
+int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad);
+uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t *addr_base);
+void MEM_WRITE(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr, unsigned int src);
+unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr);
+
+
+void MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src);
+void MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src);
+void MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src);
+void MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src);
+
+
+unsigned char MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr);
+unsigned short MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr);
+unsigned int MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr);
+uint64_t MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr);
+
+
+void MEM_WRITE_08_PASSTHROUGH(uint64_t addr, unsigned char src);
+void MEM_WRITE_16_PASSTHROUGH(uint64_t addr, unsigned short src);
+void MEM_WRITE_32_PASSTHROUGH(uint64_t addr, unsigned int src);
+void MEM_WRITE_64_PASSTHROUGH(uint64_t addr, uint64_t src);
+unsigned char MEM_LOOKUP_08_PASSTHROUGH(uint64_t addr);
+unsigned short MEM_LOOKUP_16_PASSTHROUGH(uint64_t addr);
+unsigned int MEM_LOOKUP_32_PASSTHROUGH(uint64_t addr);
+uint64_t MEM_LOOKUP_64_PASSTHROUGH(uint64_t addr);
+
+
+inline unsigned int parity(unsigned int a);
+unsigned int my_imul08(unsigned int a, unsigned int b);
+
+void vm_throw(vm_mngr_t* vm_mngr, unsigned long flags);
+int shift_right_arith(unsigned int size, int a, unsigned int b);
+unsigned int shift_right_logic(unsigned int size, unsigned int a, unsigned int b);
+int shift_left_logic(unsigned int size, unsigned int a, unsigned int b);
+/*
+int shift_left_logic_08(unsigned int a, unsigned int b);
+int shift_left_logic_16(unsigned int a, unsigned int b);
+int shift_left_logic_32(unsigned int a, unsigned int b);
+*/
+unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b);
+unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b);
+unsigned int imul_lo_op_08(char a, char b);
+unsigned int imul_lo_op_16(short a, short b);
+unsigned int imul_lo_op_32(int a, int b);
+int imul_hi_op_08(char a, char b);
+int imul_hi_op_16(short a, short b);
+int imul_hi_op_32(int a, int b);
+
+
+unsigned int umul16_lo(unsigned short a, unsigned short b);
+unsigned int umul16_hi(unsigned short a, unsigned short b);
+
+
+unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c);
+unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c);
+unsigned int rot_left(unsigned int size, unsigned int a, unsigned int b);
+unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b);
+int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf);
+int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf);
+
+//PyObject* _vm_push_uint32_t(PyObject *item);
+//PyObject* _vm_pop_uint32_t(void);
+////PyObject* _vm_put_str(PyObject *item);
+//PyObject* _vm_set_mem(PyObject *item, PyObject *item_str);
+//PyObject* _vm_set_mem_access(PyObject *addr, PyObject *access);
+//PyObject* _vm_get_str(PyObject *item, PyObject *item_len);
+//PyObject* _vm_add_memory_page(PyObject *item, PyObject *access, PyObject *item_str);
+//PyObject* _vm_add_code_bloc(PyObject *item1, PyObject *item2);//, PyObject *item3);
+//PyObject* _call_pyfunc_from_globals(char* funcname);
+//PyObject* _call_pyfunc_from_eip(void);
+//
+//PyObject* call_pyfunc_from_globals(char* funcname);
+//
+//PyObject* _vm_get_gpreg(void);
+
+void hexdump(char* m, unsigned int l);
+
+struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop);
+void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp);
+
+struct memory_page_node * create_memory_page_node(uint64_t ad, unsigned int size, unsigned int access);//memory_page* mp);
+void init_memory_page_pool(vm_mngr_t* vm_mngr);
+void init_code_bloc_pool(vm_mngr_t* vm_mngr);
+void reset_memory_page_pool(vm_mngr_t* vm_mngr);
+void reset_code_bloc_pool(vm_mngr_t* vm_mngr);
+void dump_code_bloc_pool(vm_mngr_t* vm_mngr);
+void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a);
+
+
+void init_memory_breakpoint(vm_mngr_t* vm_mngr);
+void reset_memory_breakpoint(vm_mngr_t* vm_mngr);
+void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access);
+void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access);
+
+void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn);
+
+void dump_memory_page_pool(vm_mngr_t* vm_mngr);
+void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr);
+//PyObject* _vm_get_all_memory(void);
+PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr);
+
+
+
+
+/********************************************/
+
+//PyObject* _vm_get_cpu_state(void);
+//PyObject*  _vm_set_cpu_state(PyObject * s_cpustate);
+
+
+//void memory_page_write(unsigned int my_size, uint64_t ad, unsigned int src);
+//unsigned int memory_page_read(unsigned int my_size, uint64_t ad);
+unsigned int get_memory_page_max_address(void);
+unsigned int get_memory_page_max_user_address(void);
+
+
+int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a);
+
+
+void _func_free(void);
+void _func_alloc(void);
+unsigned int _get_memory_page_max_address_py(void);
+unsigned int _get_memory_page_max_user_address_py(void);
+unsigned int _get_memory_page_from_min_ad_py(unsigned int size);
+
+void _func_malloc_memory_page(void);
+void _func_free_memory_page(void);
+void _func_virtualalloc_memory_page(void);
+void _func_virtualfree_memory_page(void);
+void _func_loadlib_fake(void);
+void _func_getproc_fake(void);
+
+
+void func_free(void);
+void func_alloc(void);
+unsigned int get_memory_page_max_address_py(void);
+unsigned int get_memory_page_max_user_address_py(void);
+unsigned int get_memory_page_from_min_ad_py(unsigned int size);
+struct memory_page_node * get_memory_page_from_address(vm_mngr_t*, uint64_t ad);
+void func_malloc_memory_page(void);
+void func_free_memory_page(void);
+void func_virtualalloc_memory_page(void);
+void func_virtualfree_memory_page(void);
+void func_loadlib_fake(void);
+void func_getproc_fake(void);
+
+
+//PyObject* _vm_exec_bloc(PyObject* my_eip, PyObject* known_blocs);
+
+unsigned int cpuid(unsigned int a, unsigned int reg_num);
+double int2double(unsigned int m);
+//PyObject* _vm_exec_blocs(PyObject* my_eip);
+
+double fadd(double a, double b);
+double fsub(double a, double b);
+double fmul(double a, double b);
+double fdiv(double a, double b);
+double ftan(double a);
+double frndint(double a);
+double fsin(double a);
+double fcos(double a);
+double fscale(double a, double b);
+double f2xm1(double a);
+double fsqrt(double a);
+double fabs(double a);
+unsigned int fcom_c0(double a, double b);
+unsigned int fcom_c1(double a, double b);
+unsigned int fcom_c2(double a, double b);
+unsigned int fcom_c3(double a, double b);
+
+
+
+double mem_32_to_double(unsigned int m);
+double mem_64_to_double(uint64_t m);
+double int_16_to_double(unsigned int m);
+double int_32_to_double(unsigned int m);
+double int_64_to_double(uint64_t m);
+int32_t double_to_int_32(double d);
+int64_t double_to_int_64(double d);
+double fadd(double a, double b);
+unsigned int double_to_mem_32(double d);
+uint64_t double_to_mem_64(double d);
+
+unsigned int access_segment(unsigned int d);
+unsigned int access_segment_ok(unsigned int d);
+
+unsigned int load_segment_limit(unsigned int d);
+unsigned int load_segment_limit_ok(unsigned int d);
+
+unsigned int load_tr_segment_selector(unsigned int d);
+
+#define shift_right_arith_08(a, b)\
+	((((char)(a)) >> ((int)(b)&0x1f))&0xff)
+#define shift_right_arith_16(a, b)\
+	((((short)(a)) >> ((int)(b)&0x1f))&0xffff)
+#define shift_right_arith_32(a, b)\
+	((((int)(a)) >> ((int)(b)&0x1f))&0xffffffff)
+
+
+#define shift_right_logic_08(a, b)\
+	((((unsigned char)(a)) >> ((unsigned int)(b)&0x1f))&0xff)
+#define shift_right_logic_16(a, b)\
+	((((unsigned short)(a)) >> ((unsigned int)(b)&0x1f))&0xffff)
+#define shift_right_logic_32(a, b)\
+	((((unsigned int)(a)) >> ((unsigned int)(b)&0x1f))&0xffffffff)
+
+#define shift_left_logic_08(a, b)\
+	(((a)<<((b)&0x1f))&0xff)
+#define shift_left_logic_16(a, b)\
+	(((a)<<((b)&0x1f))&0xffff)
+#define shift_left_logic_32(a, b)\
+	(((a)<<((b)&0x1f))&0xffffffff)
+
+#endif
diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c
new file mode 100644
index 00000000..a8085d92
--- /dev/null
+++ b/miasm2/jitter/vm_mngr_py.c
@@ -0,0 +1,939 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+#include "structmember.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "queue.h"
+#include "vm_mngr.h"
+
+#define MIN(a,b)  (((a)<(b))?(a):(b))
+#define MAX(a,b)  (((a)>(b))?(a):(b))
+
+extern struct memory_page_list_head memory_page_pool;
+extern struct code_bloc_list_head code_bloc_pool;
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+
+
+typedef struct {
+	PyObject_HEAD
+	PyObject *vmmngr;
+	vm_mngr_t vm_mngr;
+} VmMngr;
+
+
+PyObject* _vm_get_exception(unsigned int xcpt)
+{
+	PyObject*p;
+
+	if (!xcpt)
+		p = NULL;
+	else if (xcpt & EXCEPT_CODE_AUTOMOD)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_CODE_AUTOMOD" );
+	else if (xcpt & EXCEPT_UNK_EIP)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_EIP" );
+	else if (xcpt & EXCEPT_UNK_MEM_AD)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_MEM_AD" );
+
+	else  p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNKNOWN" );
+	return p;
+}
+
+
+#define PyGetInt(item, value)						\
+	if (PyInt_Check(item)){						\
+		value = (uint64_t)PyInt_AsLong(item);			\
+	}								\
+	else if (PyLong_Check(item)){					\
+		value = (uint64_t)PyLong_AsUnsignedLongLong(item);	\
+	}								\
+	else{								\
+		RAISE(PyExc_TypeError,"arg must be int");		\
+	}								\
+
+
+PyObject* vm_is_mem_mapped(VmMngr* self, PyObject* item)
+{
+	PyObject *addr;
+	uint64_t page_addr;
+	uint32_t ret;
+	if (!PyArg_ParseTuple(item, "O", &addr))
+		return NULL;
+
+	PyGetInt(addr, page_addr);
+
+	ret = is_mem_mapped(&self->vm_mngr, page_addr);
+	return PyInt_FromLong((long)ret);
+}
+
+
+
+PyObject* vm_get_mem_base_addr(VmMngr* self, PyObject* item)
+{
+	PyObject *addr;
+
+	uint64_t page_addr;
+	uint64_t addr_base;
+	unsigned int ret;
+
+	if (!PyArg_ParseTuple(item, "O", &addr))
+		return NULL;
+
+	PyGetInt(addr, page_addr);
+
+	ret = get_mem_base_addr(&self->vm_mngr, page_addr, &addr_base);
+	if (ret == 0){
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+	return PyLong_FromUnsignedLongLong((uint64_t)addr_base);
+}
+
+
+PyObject* vm_add_memory_page(VmMngr* self, PyObject* args)
+{
+	PyObject *addr;
+	PyObject *access;
+	PyObject *item_str;
+	uint64_t buf_size;
+	char* buf_data;
+	Py_ssize_t length;
+	uint64_t ret = 0x1337beef;
+	uint64_t page_addr;
+	uint64_t page_access;
+
+	struct memory_page_node * mpn;
+
+	if (!PyArg_ParseTuple(args, "OOO", &addr, &access, &item_str))
+		return NULL;
+
+	PyGetInt(addr, page_addr);
+	PyGetInt(access, page_access);
+
+	if(!PyString_Check(item_str))
+		RAISE(PyExc_TypeError,"arg must be str");
+
+	buf_size = PyString_Size(item_str);
+	PyString_AsStringAndSize(item_str, &buf_data, &length);
+
+	fprintf(stderr, "add page %"PRIX64" %"PRIX64" %"PRIX64"\n", page_addr, buf_size, page_access);
+	mpn = create_memory_page_node(page_addr, buf_size, page_access);
+	if (mpn == NULL)
+		RAISE(PyExc_TypeError,"cannot create page");
+	if (is_mpn_in_tab(&self->vm_mngr, mpn))
+		RAISE(PyExc_TypeError,"known page in memory");
+
+	memcpy(mpn->ad_hp, buf_data, buf_size);
+	add_memory_page(&self->vm_mngr, mpn);
+
+	return PyLong_FromUnsignedLongLong((uint64_t)ret);
+
+}
+
+
+
+
+PyObject* vm_set_mem(VmMngr* self, PyObject* args)
+{
+	PyObject *addr;
+	PyObject *item_str;
+
+	uint64_t buf_size;
+	char* buf_data;
+	Py_ssize_t length;
+	int ret = 0x1337;
+	uint64_t val;
+	uint64_t l;
+
+	struct memory_page_node * mpn;
+
+	if (!PyArg_ParseTuple(args, "OO", &addr, &item_str))
+		return NULL;
+
+	PyGetInt(addr, val);
+
+	if(!PyString_Check(item_str))
+		RAISE(PyExc_TypeError,"arg must be str");
+
+	buf_size = PyString_Size(item_str);
+	PyString_AsStringAndSize(item_str, &buf_data, &length);
+
+	/* read is multiple page wide */
+	while (buf_size){
+		mpn = get_memory_page_from_address(&self->vm_mngr, val);
+		if (!mpn){
+			PyErr_SetString(PyExc_RuntimeError, "cannot find address");
+			return 0;
+		}
+		l = MIN(buf_size, mpn->size - (val-mpn->ad));
+		memcpy(mpn->ad_hp + (val-mpn->ad), buf_data, l);
+		buf_data += l;
+		val += l;
+		buf_size -= l;
+	}
+
+	return PyLong_FromUnsignedLongLong((uint64_t)ret);
+}
+
+PyObject* vm_set_mem_access(VmMngr* self, PyObject* args)
+{
+	PyObject *addr;
+	PyObject *access;
+
+	uint64_t ret = 0x1337beef;
+	uint64_t page_addr;
+	uint64_t page_access;
+	struct memory_page_node * mpn;
+
+	if (!PyArg_ParseTuple(args, "OO", &addr, &access))
+		return NULL;
+
+	PyGetInt(addr, page_addr);
+	PyGetInt(access, page_access);
+
+	mpn = get_memory_page_from_address(&self->vm_mngr, page_addr);
+	mpn->access = page_access;
+	return PyLong_FromUnsignedLongLong((uint64_t)ret);
+}
+
+
+
+
+PyObject* vm_get_mem(VmMngr* self, PyObject* args)
+{
+	PyObject *item;
+	PyObject *item_len;
+
+	uint64_t buf_addr;
+	uint64_t buf_len;
+	PyObject *obj_out;
+	struct memory_page_node * mpn;
+	char * buf_out;
+	char * addr_tmp;
+	char * addr_out;
+	uint64_t off;
+	uint64_t l;
+	uint64_t my_size;
+
+	if (!PyArg_ParseTuple(args, "OO", &item, &item_len))
+		return NULL;
+
+	PyGetInt(item, buf_addr);
+	PyGetInt(item_len, buf_len);
+
+	my_size = buf_len;
+	buf_out = malloc(buf_len);
+	if (!buf_out){
+		fprintf(stderr, "cannot alloc read\n");
+		exit(-1);
+	}
+
+	addr_out = buf_out;
+
+	/* read is multiple page wide */
+	while (my_size){
+		mpn = get_memory_page_from_address(&self->vm_mngr, buf_addr);
+		if (!mpn){
+			PyErr_SetString(PyExc_RuntimeError, "cannot find address");
+			return 0;
+		}
+
+		off = buf_addr - mpn->ad;
+		addr_tmp = &((char*)mpn->ad_hp)[off];
+
+		l = MIN(my_size, mpn->size - off);
+		memcpy(addr_out, addr_tmp, l);
+		my_size -= l;
+		addr_out +=l;
+		buf_addr +=l;
+	}
+
+	obj_out = PyString_FromStringAndSize(buf_out, buf_len);
+	free(buf_out);
+	return obj_out;
+}
+
+PyObject* vm_add_memory_breakpoint(VmMngr* self, PyObject* args)
+{
+	PyObject *ad;
+	PyObject *size;
+	PyObject *access;
+
+	uint64_t b_ad;
+	uint64_t b_size;
+	uint64_t b_access;
+
+	if (!PyArg_ParseTuple(args, "OOO", &ad, &size, &access))
+		return NULL;
+
+	PyGetInt(ad, b_ad);
+	PyGetInt(size, b_size);
+	PyGetInt(access, b_access);
+
+	add_memory_breakpoint(&self->vm_mngr, b_ad, b_size, b_access);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_remove_memory_breakpoint(VmMngr* self, PyObject* args)
+{
+	PyObject *ad;
+	PyObject *access;
+	uint64_t b_ad;
+	uint64_t b_access;
+
+	if (!PyArg_ParseTuple(args, "OO", &ad, &access))
+		return NULL;
+
+	PyGetInt(ad, b_ad);
+	PyGetInt(access, b_access);
+	remove_memory_breakpoint(&self->vm_mngr, b_ad, b_access);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_get_last_write_ad(VmMngr* self, PyObject* args)
+{
+	return PyInt_FromLong((uint64_t)self->vm_mngr.last_write_ad);
+}
+
+PyObject* vm_get_last_write_size(VmMngr* self, PyObject* args)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)self->vm_mngr.last_write_size);
+}
+
+PyObject* vm_set_exception(VmMngr* self, PyObject* args)
+{
+	PyObject *item1;
+	uint64_t i;
+
+	if (!PyArg_ParseTuple(args, "O", &item1))
+		return NULL;
+
+	PyGetInt(item1, i);
+
+	self->vm_mngr.exception_flags = i;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_exception(VmMngr* self, PyObject* args)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)self->vm_mngr.exception_flags);
+}
+
+
+
+
+PyObject* vm_init_memory_page_pool(VmMngr* self, PyObject* args)
+{
+    init_memory_page_pool(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* vm_init_code_bloc_pool(VmMngr* self, PyObject* args)
+{
+    init_code_bloc_pool(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+PyObject* vm_init_memory_breakpoint(VmMngr* self, PyObject* args)
+{
+    init_memory_breakpoint(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+PyObject* vm_reset_memory_breakpoint(VmMngr* self, PyObject* args)
+{
+    reset_memory_breakpoint(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+
+
+
+
+
+PyObject* vm_dump_memory_page_pool(VmMngr* self, PyObject* args)
+{
+	dump_memory_page_pool(&self->vm_mngr);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_dump_memory_breakpoint(VmMngr* self, PyObject* args)
+{
+	dump_memory_breakpoint_pool(&self->vm_mngr);
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+PyObject* vm_get_all_memory(VmMngr* self, PyObject* args)
+{
+	PyObject *o;
+	struct memory_page_node * mpn;
+	PyObject *dict;
+	PyObject *dict2;
+
+
+	dict =  PyDict_New();
+
+	LIST_FOREACH(mpn, &self->vm_mngr.memory_page_pool, next){
+
+		dict2 =  PyDict_New();
+
+		o = PyString_FromStringAndSize(mpn->ad_hp, mpn->size);
+		PyDict_SetItemString(dict2, "data", o);
+		Py_DECREF(o);
+
+		o = PyInt_FromLong((long)mpn->size);
+		PyDict_SetItemString(dict2, "size", o);
+		Py_DECREF(o);
+
+		o = PyInt_FromLong((long)mpn->access);
+		PyDict_SetItemString(dict2, "access", o);
+		Py_DECREF(o);
+
+		o = PyInt_FromLong((long)mpn->ad);
+		PyDict_SetItem(dict, o, dict2);
+		Py_DECREF(o);
+		Py_DECREF(dict2);
+	}
+	return dict;
+}
+
+
+PyObject* vm_reset_memory_page_pool(VmMngr* self, PyObject* args)
+{
+    reset_memory_page_pool(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+PyObject* vm_reset_code_bloc_pool(VmMngr* self, PyObject* args)
+{
+    reset_code_bloc_pool(&self->vm_mngr);
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+
+
+
+
+
+PyObject* vm_call_pyfunc_from_globals(VmMngr* self, PyObject* args)
+{
+	char* funcname;
+	PyObject  *mod,  *func, *rslt, *globals, *func_globals;
+
+
+	if (!PyArg_ParseTuple(args, "s", &funcname))
+		return NULL;
+
+
+	fprintf(stderr, "getting pyfunc %s\n", funcname);
+	mod = PyEval_GetBuiltins();
+
+	if (!mod) {
+		fprintf(stderr, "cannot find module\n");
+		exit(0);
+	}
+
+	func_globals = PyDict_GetItemString(mod, "globals");
+	if (!func_globals) {
+		fprintf(stderr, "cannot find function globals\n");
+		exit(0);
+	}
+
+	if (!PyCallable_Check (func_globals)) {
+		fprintf(stderr, "function not callable\n");
+		exit(0);
+	}
+
+	globals = PyObject_CallObject (func_globals, NULL);
+	if (!globals) {
+		fprintf(stderr, "cannot get globals\n");
+		exit(0);
+	}
+
+	func = PyDict_GetItemString (globals, funcname);
+	if (!func) {
+		fprintf(stderr, "cannot find function %s\n", funcname);
+		exit(0);
+	}
+
+	if (!PyCallable_Check (func)) {
+		fprintf(stderr, "function not callable\n");
+		exit(0);
+	}
+
+	rslt = PyObject_CallObject (func, NULL);
+	return rslt;
+}
+
+PyObject* vm_add_code_bloc(VmMngr *self, PyObject *args)
+{
+	PyObject *item1;
+	PyObject *item2;
+	uint64_t ret = 0x1337beef;
+	uint64_t ad_start, ad_stop, ad_code = 0;
+
+	struct code_bloc_node * cbp;
+
+	if (!PyArg_ParseTuple(args, "OO", &item1, &item2))
+		return NULL;
+
+	PyGetInt(item1, ad_start);
+	PyGetInt(item2, ad_stop);
+
+	cbp = create_code_bloc_node(ad_start, ad_stop);
+	cbp->ad_start = ad_start;
+	cbp->ad_stop = ad_stop;
+	cbp->ad_code = ad_code;
+	add_code_bloc(&self->vm_mngr, cbp);
+	return PyLong_FromUnsignedLongLong((uint64_t)ret);
+}
+
+PyObject* vm_dump_code_bloc_pool(VmMngr* self)
+{
+	dump_code_bloc_pool(&self->vm_mngr);
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+
+PyObject* vm_exec_blocs(VmMngr* self, PyObject* args)
+{
+	PyObject* my_eip;
+	PyObject* b;
+	PyObject* module;
+	PyObject* func;
+	PyObject* meip;
+	uint64_t tmp;
+
+	PyObject* known_blocs;
+	PyObject* e;
+
+	if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs))
+		return NULL;
+
+	if(!PyDict_Check(known_blocs))
+		RAISE(PyExc_TypeError, "arg must be dict");
+
+	PyGetInt(my_eip, tmp);
+	meip = PyLong_FromUnsignedLongLong((uint64_t)tmp);
+	while (1){
+		b = PyDict_GetItem(known_blocs, meip);
+		if (b == NULL)
+			return meip;
+
+		module = PyObject_GetAttrString(b, "module_c");
+		if (module == NULL){
+			fprintf(stderr, "assert eip module_c in pyobject\n");
+			exit(0);
+		}
+		func = PyObject_GetAttrString(module, "func");
+		if (func == NULL){
+			fprintf(stderr, "assert func module_c in pyobject\n");
+			exit(0);
+		}
+
+		Py_DECREF(module);
+		if (!PyCallable_Check (func)) {
+			fprintf(stderr, "function not callable\n");
+			exit(0);
+		}
+		Py_DECREF(meip);
+		//printf("exec bloc %"PRIX64"\n", tmp);
+		meip = PyObject_CallObject (func, NULL);
+
+		Py_DECREF(func);
+		e = PyErr_Occurred ();
+		if (e){
+			fprintf(stderr, "exception\n");
+			return meip;
+		}
+
+		if (self->vm_mngr.exception_flags)
+			return meip;
+
+	}
+}
+
+
+
+PyObject* vm_exec_bloc(PyObject* self, PyObject* args)
+{
+	PyObject* b;
+	PyObject* module;
+	PyObject* func;
+	PyObject* meip;
+	uint64_t tmp;
+
+	PyObject* my_eip;
+	PyObject* known_blocs;
+	PyObject* e;
+
+	if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs))
+		return NULL;
+
+
+	if (PyInt_Check(my_eip)){
+		tmp = (uint64_t)PyInt_AsLong(my_eip);
+	}
+	else if (PyLong_Check(my_eip)){
+		tmp = (uint64_t)PyLong_AsUnsignedLongLong(my_eip);
+	}
+	else{
+		RAISE(PyExc_TypeError,"arg1 must be int");
+	}
+
+	meip = PyInt_FromLong((long)tmp);
+	b = PyDict_GetItem(known_blocs, my_eip);
+	if (b == NULL)
+		return meip;
+	module = PyObject_GetAttrString(b, "module_c");
+	if (module == NULL)
+		return meip;
+	func = PyObject_GetAttrString(module, "func");
+	if (func == NULL)
+		return meip;
+	Py_DECREF(module);
+	if (!PyCallable_Check (func)) {
+		fprintf(stderr, "function not callable\n");
+		exit(0);
+	}
+	Py_DECREF(meip);
+	meip = PyObject_CallObject (func, NULL);
+
+	Py_DECREF(func);
+	e = PyErr_Occurred ();
+	if (e){
+		fprintf(stderr, "exception\n");
+		return meip;
+	}
+
+	return meip;
+}
+
+
+PyObject* vm_set_automod_cb(VmMngr* self, PyObject* args)
+{
+	PyObject* cb_automod;
+
+	if (!PyArg_ParseTuple(args, "O", &cb_automod))
+		return NULL;
+
+	if (self->vm_mngr.cb_automod != NULL){
+		Py_DECREF(self->vm_mngr.cb_automod);
+	}
+
+	Py_INCREF(cb_automod);
+	self->vm_mngr.cb_automod = cb_automod;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_set_addr2obj(VmMngr* self, PyObject* args)
+{
+	PyObject* addr2obj;
+
+	if (!PyArg_ParseTuple(args, "O", &addr2obj))
+		return NULL;
+
+	if (self->vm_mngr.addr2obj != NULL){
+		Py_DECREF(self->vm_mngr.addr2obj);
+	}
+
+	Py_INCREF(addr2obj);
+	self->vm_mngr.addr2obj = addr2obj;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+
+
+/*
+PyObject* add_jitbloc(VmMngr* self, PyObject* args)
+{
+	PyObject* jitobj;
+
+	if (!PyArg_ParseTuple(args, "O", &addr2obj))
+		return NULL;
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+*/
+
+
+
+
+static void
+VmMngr_dealloc(VmMngr* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static PyObject *
+VmMngr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    VmMngr *self;
+
+    self = (VmMngr *)type->tp_alloc(type, 0);
+    return (PyObject *)self;
+}
+
+static PyObject *
+VmMngr_get_vmmngr(VmMngr *self, void *closure)
+{
+	return PyLong_FromUnsignedLongLong((uint64_t)&(self->vm_mngr));
+}
+
+static int
+VmMngr_set_vmmngr(VmMngr *self, PyObject *value, void *closure)
+{
+	PyErr_SetString(PyExc_TypeError, "immutable vmmngr");
+	return -1;
+}
+
+static PyMemberDef VmMngr_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef VmMngr_methods[] = {
+	{"vm_init_memory_page_pool", (PyCFunction)vm_init_memory_page_pool, METH_VARARGS,
+	 "X"},
+	{"vm_init_memory_breakpoint", (PyCFunction)vm_init_memory_breakpoint, METH_VARARGS,
+	 "X"},
+	{"vm_init_code_bloc_pool",(PyCFunction)vm_init_code_bloc_pool, METH_VARARGS,
+	 "X"},
+	{"vm_set_mem_access", (PyCFunction)vm_set_mem_access, METH_VARARGS,
+	 "X"},
+	{"vm_set_mem", (PyCFunction)vm_set_mem, METH_VARARGS,
+	 "X"},
+	{"vm_set_automod_cb", (PyCFunction)vm_set_automod_cb, METH_VARARGS,
+	 "X"},
+	{"vm_set_addr2obj", (PyCFunction)vm_set_addr2obj, METH_VARARGS,
+	 "X"},
+	{"vm_add_code_bloc",(PyCFunction)vm_add_code_bloc, METH_VARARGS,
+	 "X"},
+	{"vm_exec_bloc",(PyCFunction)vm_exec_bloc, METH_VARARGS,
+	 "X"},
+	{"vm_exec_blocs",(PyCFunction)vm_exec_blocs, METH_VARARGS,
+	 "X"},
+	{"vm_get_mem", (PyCFunction)vm_get_mem, METH_VARARGS,
+	 "X"},
+	{"vm_add_memory_page",(PyCFunction)vm_add_memory_page, METH_VARARGS,
+	 "X"},
+	{"vm_add_memory_breakpoint",(PyCFunction)vm_add_memory_breakpoint, METH_VARARGS,
+	 "X"},
+	{"vm_remove_memory_breakpoint",(PyCFunction)vm_remove_memory_breakpoint, METH_VARARGS,
+	 "X"},
+	{"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS,
+	 "X"},
+	{"vm_dump_memory_page_pool", (PyCFunction)vm_dump_memory_page_pool, METH_VARARGS,
+	 "X"},
+	{"vm_dump_memory_breakpoint", (PyCFunction)vm_dump_memory_breakpoint, METH_VARARGS,
+	 "X"},
+	{"vm_get_all_memory",(PyCFunction)vm_get_all_memory, METH_VARARGS,
+	 "X"},
+	{"vm_reset_memory_page_pool", (PyCFunction)vm_reset_memory_page_pool, METH_VARARGS,
+	 "X"},
+	{"vm_reset_memory_breakpoint", (PyCFunction)vm_reset_memory_breakpoint, METH_VARARGS,
+	 "X"},
+	{"vm_reset_code_bloc_pool", (PyCFunction)vm_reset_code_bloc_pool, METH_VARARGS,
+	 "X"},
+	{"vm_call_pyfunc_from_globals",(PyCFunction)vm_call_pyfunc_from_globals, METH_VARARGS,
+	 "X"},
+
+	{"vm_get_exception",(PyCFunction)vm_get_exception, METH_VARARGS,
+	 "X"},
+	{"vm_get_exception",(PyCFunction)vm_get_exception, METH_VARARGS,
+	 "X"},
+	{"vm_get_last_write_ad", (PyCFunction)vm_get_last_write_ad, METH_VARARGS,
+	 "X"},
+	{"vm_get_last_write_size",(PyCFunction)vm_get_last_write_size, METH_VARARGS,
+	 "X"},
+
+	{NULL}  /* Sentinel */
+};
+
+static int
+VmMngr_init(VmMngr *self, PyObject *args, PyObject *kwds)
+{
+
+
+	fprintf(stderr, "ad cpu: %p\n", &(self->vm_mngr));
+	memset(&(self->vm_mngr), 0, sizeof(self->vm_mngr));
+	return 0;
+}
+
+static PyGetSetDef VmMngr_getseters[] = {
+    {"vmmngr",
+     (getter)VmMngr_get_vmmngr, (setter)VmMngr_set_vmmngr,
+     "first name",
+     NULL},
+    {NULL}  /* Sentinel */
+};
+
+
+static PyTypeObject VmMngrType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "JitCore_x86_32.VmMngr",   /*tp_name*/
+    sizeof(VmMngr),            /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)VmMngr_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "VmMngr objects",          /* tp_doc */
+    0,			       /* tp_traverse */
+    0,			       /* tp_clear */
+    0,			       /* tp_richcompare */
+    0,			       /* tp_weaklistoffset */
+    0,			       /* tp_iter */
+    0,			       /* tp_iternext */
+    VmMngr_methods,            /* tp_methods */
+    VmMngr_members,            /* tp_members */
+    VmMngr_getseters,          /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)VmMngr_init,     /* tp_init */
+    0,                         /* tp_alloc */
+    VmMngr_new,                /* tp_new */
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static PyObject *Vm_Mngr_Error;
+
+
+static PyMethodDef Vm_Mngr_Methods[] = {
+
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+
+};
+
+
+PyMODINIT_FUNC
+initvm_mngr(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&VmMngrType) < 0)
+	return;
+
+    m = Py_InitModule("vm_mngr", Vm_Mngr_Methods);
+    if (m == NULL)
+	    return;
+
+    Vm_Mngr_Error = PyErr_NewException("vm_mngr_.error", NULL, NULL);
+    Py_INCREF(Vm_Mngr_Error);
+    PyModule_AddObject(m, "error", Vm_Mngr_Error);
+
+    Py_INCREF(&VmMngrType);
+    PyModule_AddObject(m, "VmMngr", (PyObject *)&VmMngrType);
+
+}
+