about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]example/asm/shellcode.py2
-rwxr-xr-x[-rw-r--r--]example/jitter/arm.py2
-rwxr-xr-x[-rw-r--r--]example/jitter/arm_sc.py2
-rwxr-xr-x[-rw-r--r--]example/jitter/example_types.py2
-rwxr-xr-x[-rw-r--r--]example/jitter/mips32.py2
-rwxr-xr-x[-rw-r--r--]example/jitter/msp430.py2
-rw-r--r--miasm2/analysis/disasm_cb.py1
-rw-r--r--miasm2/analysis/gdbserver.py1
-rw-r--r--miasm2/analysis/machine.py1
-rw-r--r--miasm2/arch/aarch64/arch.py1
-rw-r--r--miasm2/arch/aarch64/ira.py1
-rw-r--r--miasm2/arch/aarch64/regs.py1
-rw-r--r--miasm2/arch/arm/arch.py1
-rw-r--r--miasm2/arch/arm/ira.py1
-rw-r--r--miasm2/arch/arm/regs.py1
-rw-r--r--miasm2/arch/mips32/arch.py1
-rw-r--r--miasm2/arch/mips32/ira.py1
-rw-r--r--miasm2/arch/mips32/regs.py1
-rw-r--r--miasm2/arch/msp430/arch.py1
-rw-r--r--miasm2/arch/msp430/ira.py1
-rw-r--r--miasm2/arch/msp430/sem.py1
-rw-r--r--miasm2/arch/sh4/arch.py1
-rw-r--r--miasm2/arch/x86/arch.py1
-rw-r--r--miasm2/arch/x86/ira.py1
-rw-r--r--miasm2/arch/x86/sem.py13
-rw-r--r--miasm2/core/asmbloc.py1
-rw-r--r--miasm2/core/cpu.py1
-rw-r--r--miasm2/core/parse_asm.py1
-rw-r--r--miasm2/expression/__init__.py1
-rw-r--r--miasm2/expression/modint.py1
-rw-r--r--miasm2/ir/analysis.py1
-rw-r--r--miasm2/ir/ir.py1
-rw-r--r--miasm2/jitter/Jitllvm.c63
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c3
-rw-r--r--miasm2/jitter/csts.py1
-rw-r--r--miasm2/jitter/jitcore.py21
-rw-r--r--miasm2/jitter/jitcore_cc_base.py1
-rw-r--r--miasm2/jitter/jitcore_gcc.py1
-rw-r--r--miasm2/jitter/jitcore_llvm.py85
-rw-r--r--miasm2/jitter/jitcore_python.py13
-rw-r--r--miasm2/jitter/jitcore_tcc.py1
-rw-r--r--miasm2/jitter/jitload.py3
-rw-r--r--miasm2/jitter/llvmconvert.py82
-rw-r--r--miasm2/os_dep/linux_stdlib.py1
-rw-r--r--miasm2/os_dep/win_api_x86_32_seh.py1
-rw-r--r--test/arch/aarch64/unit/asm_test.py8
-rwxr-xr-x[-rw-r--r--]test/arch/aarch64/unit/mn_ubfm.py3
-rwxr-xr-x[-rw-r--r--]test/arch/arm/sem.py2
-rw-r--r--test/arch/mips32/unit/asm_test.py8
-rwxr-xr-x[-rw-r--r--]test/arch/mips32/unit/mn_bcc.py3
-rwxr-xr-x[-rw-r--r--]test/arch/msp430/sem.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/sem.py2
-rw-r--r--test/arch/x86/unit/asm_test.py8
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_daa.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_das.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_float.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_int.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pcmpeq.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pextr.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pinsr.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pmaxu.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pminu.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pmovmskb.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pshufb.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_psrl_psll.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_punpck.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_pushpop.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_seh.py2
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_stack.py3
-rwxr-xr-x[-rw-r--r--]test/arch/x86/unit/mn_strings.py2
-rwxr-xr-x[-rw-r--r--]test/core/interval.py2
-rwxr-xr-x[-rw-r--r--]test/core/parse_asm.py2
-rwxr-xr-x[-rw-r--r--]test/core/test_types.py2
-rwxr-xr-x[-rw-r--r--]test/core/utils.py3
-rwxr-xr-x[-rw-r--r--]test/expression/expression_helper.py2
-rwxr-xr-x[-rw-r--r--]test/expression/stp.py2
-rw-r--r--[-rwxr-xr-x]test/ir/analysis.py0
-rwxr-xr-x[-rw-r--r--]test/ir/ir2C.py2
-rwxr-xr-x[-rw-r--r--]test/ir/symbexec.py2
-rw-r--r--test/jitter/jit_options.py97
-rw-r--r--test/jitter/jitload.py3
-rw-r--r--test/jitter/vm_mngr.py3
-rwxr-xr-x[-rw-r--r--]test/os_dep/win_api_x86_32.py2
-rwxr-xr-x[-rw-r--r--]test/test_all.py9
84 files changed, 374 insertions, 160 deletions
diff --git a/example/asm/shellcode.py b/example/asm/shellcode.py
index f31c88c2..3ff11489 100644..100755
--- a/example/asm/shellcode.py
+++ b/example/asm/shellcode.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 from argparse import ArgumentParser
 from pdb import pm
 
diff --git a/example/jitter/arm.py b/example/jitter/arm.py
index 7bd354bc..eac6c0e6 100644..100755
--- a/example/jitter/arm.py
+++ b/example/jitter/arm.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 import logging
 from pdb import pm
diff --git a/example/jitter/arm_sc.py b/example/jitter/arm_sc.py
index ca765d31..6644a440 100644..100755
--- a/example/jitter/arm_sc.py
+++ b/example/jitter/arm_sc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 from miasm2.analysis.sandbox import Sandbox_Linux_armb_str
 from miasm2.analysis.sandbox import Sandbox_Linux_arml_str
diff --git a/example/jitter/example_types.py b/example/jitter/example_types.py
index c37c3b84..7ed964c2 100644..100755
--- a/example/jitter/example_types.py
+++ b/example/jitter/example_types.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 """This script is just a short example of common usages for miasm2.core.types.
 For a more complete view of what is possible, tests/core/types.py covers
 most of the module possibilities, and the module doc gives useful information
diff --git a/example/jitter/mips32.py b/example/jitter/mips32.py
index a03cac8e..7c8900f8 100644..100755
--- a/example/jitter/mips32.py
+++ b/example/jitter/mips32.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 from argparse import ArgumentParser
 from miasm2.analysis import debugging
diff --git a/example/jitter/msp430.py b/example/jitter/msp430.py
index 89ecd930..5c8b7197 100644..100755
--- a/example/jitter/msp430.py
+++ b/example/jitter/msp430.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 from argparse import ArgumentParser
 from miasm2.analysis import debugging
diff --git a/miasm2/analysis/disasm_cb.py b/miasm2/analysis/disasm_cb.py
index b6c4351d..f1f23377 100644
--- a/miasm2/analysis/disasm_cb.py
+++ b/miasm2/analysis/disasm_cb.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import ExprInt, ExprId, ExprMem, MatchExpr
diff --git a/miasm2/analysis/gdbserver.py b/miasm2/analysis/gdbserver.py
index cbc8fe8d..dbf1b3b6 100644
--- a/miasm2/analysis/gdbserver.py
+++ b/miasm2/analysis/gdbserver.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import socket
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py
index 6215a21b..7a6069c0 100644
--- a/miasm2/analysis/machine.py
+++ b/miasm2/analysis/machine.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 
diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py
index b495821b..c875d787 100644
--- a/miasm2/arch/aarch64/arch.py
+++ b/miasm2/arch/aarch64/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/arch/aarch64/ira.py b/miasm2/arch/aarch64/ira.py
index 090ff6d0..3441483c 100644
--- a/miasm2/arch/aarch64/ira.py
+++ b/miasm2/arch/aarch64/ira.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/aarch64/regs.py b/miasm2/arch/aarch64/regs.py
index 6130d075..95527be3 100644
--- a/miasm2/arch/aarch64/regs.py
+++ b/miasm2/arch/aarch64/regs.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py
index 04e47585..0e58008d 100644
--- a/miasm2/arch/arm/arch.py
+++ b/miasm2/arch/arm/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/arch/arm/ira.py b/miasm2/arch/arm/ira.py
index 7d8e1838..d888d598 100644
--- a/miasm2/arch/arm/ira.py
+++ b/miasm2/arch/arm/ira.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/arm/regs.py b/miasm2/arch/arm/regs.py
index 1393c372..a44878a8 100644
--- a/miasm2/arch/arm/regs.py
+++ b/miasm2/arch/arm/regs.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/mips32/arch.py b/miasm2/arch/mips32/arch.py
index 38ed2811..2ac16770 100644
--- a/miasm2/arch/mips32/arch.py
+++ b/miasm2/arch/mips32/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py
index ecbc1a7f..ec63c8c7 100644
--- a/miasm2/arch/mips32/ira.py
+++ b/miasm2/arch/mips32/ira.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py
index b64b40d5..974d3a2b 100644
--- a/miasm2/arch/mips32/regs.py
+++ b/miasm2/arch/mips32/regs.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import ExprId
diff --git a/miasm2/arch/msp430/arch.py b/miasm2/arch/msp430/arch.py
index ce0fe70f..a9f695ec 100644
--- a/miasm2/arch/msp430/arch.py
+++ b/miasm2/arch/msp430/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/arch/msp430/ira.py b/miasm2/arch/msp430/ira.py
index 8e6aecee..bf777775 100644
--- a/miasm2/arch/msp430/ira.py
+++ b/miasm2/arch/msp430/ira.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/msp430/sem.py b/miasm2/arch/msp430/sem.py
index 92b005ad..4b52361d 100644
--- a/miasm2/arch/msp430/sem.py
+++ b/miasm2/arch/msp430/sem.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import *
diff --git a/miasm2/arch/sh4/arch.py b/miasm2/arch/sh4/arch.py
index 7c76e003..d72e6945 100644
--- a/miasm2/arch/sh4/arch.py
+++ b/miasm2/arch/sh4/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from pyparsing import *
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 87e91756..90d0fcef 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import re
diff --git a/miasm2/arch/x86/ira.py b/miasm2/arch/x86/ira.py
index 30dc92b0..d772d9fc 100644
--- a/miasm2/arch/x86/ira.py
+++ b/miasm2/arch/x86/ira.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from miasm2.expression.expression import ExprAff, ExprOp, ExprId
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 152208d4..ea5830e3 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -1732,9 +1732,11 @@ def float_pop(avoid_flt=None, popcount=1):
         if avoid_flt != float_list[i]:
             e.append(m2_expr.ExprAff(float_list[i],
                                      float_list[i + popcount]))
+    fill_value = m2_expr.ExprOp("int_64_to_double",
+                                m2_expr.ExprInt(0, float_list[i].size))
     for i in xrange(8 - popcount, 8):
         e.append(m2_expr.ExprAff(float_list[i],
-                                 m2_expr.ExprInt(0, float_list[i].size)))
+                                 fill_value))
     e.append(
         m2_expr.ExprAff(float_stack_ptr,
                         float_stack_ptr - m2_expr.ExprInt(popcount, 3)))
@@ -2906,13 +2908,20 @@ def bittest_get(a, b):
         b_mask = {16: 4, 32: 5, 64: 6}
         b_decal = {16: 1, 32: 3, 64: 7}
         ptr = a.arg
+        segm = a.is_op_segm()
+        if segm:
+            ptr = ptr.args[1]
+
         off_bit = b.zeroExtend(
             a.size) & m2_expr.ExprInt((1 << b_mask[a.size]) - 1,
                                       a.size)
         off_byte = ((b.zeroExtend(ptr.size) >> m2_expr.ExprInt(3, ptr.size)) &
                     m2_expr.ExprInt(((1 << a.size) - 1) ^ b_decal[a.size], ptr.size))
 
-        d = m2_expr.ExprMem(ptr + off_byte, a.size)
+        addr = ptr + off_byte
+        if segm:
+            addr = m2_expr.ExprOp("segm", a.arg.args[0], addr)
+        d = m2_expr.ExprMem(addr, a.size)
     else:
         off_bit = m2_expr.ExprOp('&', b, m2_expr.ExprInt(a.size - 1, a.size))
         d = a
diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py
index 730d6d7d..b68b1f1c 100644
--- a/miasm2/core/asmbloc.py
+++ b/miasm2/core/asmbloc.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py
index 7a2968f9..22f4c8ab 100644
--- a/miasm2/core/cpu.py
+++ b/miasm2/core/cpu.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import re
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py
index b324d2cc..238306b3 100644
--- a/miasm2/core/parse_asm.py
+++ b/miasm2/core/parse_asm.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 import re
 
diff --git a/miasm2/expression/__init__.py b/miasm2/expression/__init__.py
index 2bf12b34..67f567f7 100644
--- a/miasm2/expression/__init__.py
+++ b/miasm2/expression/__init__.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #
 # Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
 #
diff --git a/miasm2/expression/modint.py b/miasm2/expression/modint.py
index a801c948..90dabfac 100644
--- a/miasm2/expression/modint.py
+++ b/miasm2/expression/modint.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 class moduint(object):
diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py
index c606d958..0913019b 100644
--- a/miasm2/ir/analysis.py
+++ b/miasm2/ir/analysis.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import logging
diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py
index 87a70205..0a7d68ce 100644
--- a/miasm2/ir/ir.py
+++ b/miasm2/ir/ir.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 #
diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c
index c176a4b2..b46f88e3 100644
--- a/miasm2/jitter/Jitllvm.c
+++ b/miasm2/jitter/Jitllvm.c
@@ -12,19 +12,66 @@
 
 PyObject* llvm_exec_bloc(PyObject* self, PyObject* args)
 {
-	uint64_t func_addr;
 	uint64_t (*func)(void*, void*, void*, uint8_t*);
-	uint64_t vm;
+	vm_cpu_t* cpu;
+	vm_mngr_t* vm;
 	uint64_t ret;
 	JitCpu* jitcpu;
 	uint8_t status;
-	
-	if (!PyArg_ParseTuple(args, "KOK", &func_addr, &jitcpu, &vm))
+	PyObject* func_py;
+	PyObject* lbl2ptr;
+	PyObject* breakpoints;
+	PyObject* retaddr = NULL;
+	uint64_t max_exec_per_call = 0;
+	uint64_t cpt;
+	int do_cpt;
+
+	if (!PyArg_ParseTuple(args, "OOOO|K",
+			      &retaddr, &jitcpu, &lbl2ptr, &breakpoints,
+			      &max_exec_per_call))
 		return NULL;
-	vm_cpu_t* cpu = jitcpu->cpu;
-	func = (void *) (intptr_t) func_addr;
-	ret = func((void*) jitcpu, (void*)(intptr_t) cpu, (void*)(intptr_t) vm, &status);
-	return PyLong_FromUnsignedLongLong(ret);
+
+	cpu = jitcpu->cpu;
+	vm = &(jitcpu->pyvm->vm_mngr);
+	/* The loop will decref retaddr always once */
+	Py_INCREF(retaddr);
+
+	if (max_exec_per_call == 0) {
+		do_cpt = 0;
+		cpt = 1;
+	} else {
+		do_cpt = 1;
+		cpt = max_exec_per_call;
+	}
+
+	for (;;) {
+		// Handle cpt
+		if (cpt == 0)
+			return retaddr;
+		if (do_cpt)
+			cpt --;
+
+		// Get the expected jitted function address
+		func_py = PyDict_GetItem(lbl2ptr, retaddr);
+		if (func_py)
+			func = PyLong_AsVoidPtr((PyObject*) func_py);
+		else
+			// retaddr is not jitted yet
+			return retaddr;
+
+		// Execute it
+		ret = func((void*) jitcpu, (void*)(intptr_t) cpu, (void*)(intptr_t) vm, &status);
+		Py_DECREF(retaddr);
+		retaddr = PyLong_FromUnsignedLongLong(ret);
+
+		// Check exception
+		if (status)
+			return retaddr;
+
+		// Check breakpoint
+		if (PyDict_Contains(breakpoints, retaddr))
+			return retaddr;
+	}
 }
 
 
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
index 66c3fb56..461e2224 100644
--- a/miasm2/jitter/arch/JitCore_x86.c
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -603,6 +603,9 @@ PyObject* get_gpreg_offset_all(void)
     get_reg_off(exception_flags);
 
     get_reg_off(float_stack_ptr);
+    get_reg_off(reg_float_cs);
+    get_reg_off(reg_float_eip);
+    get_reg_off(reg_float_control);
 
     return dict;
 }
diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py
index 95cd34a8..8efd5626 100644
--- a/miasm2/jitter/csts.py
+++ b/miasm2/jitter/csts.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
index f3a79bee..7e831280 100644
--- a/miasm2/jitter/jitcore.py
+++ b/miasm2/jitter/jitcore.py
@@ -165,33 +165,22 @@ class JitCore(object):
         # Update jitcode mem range
         self.add_bloc_to_mem_interval(vm, cur_bloc)
 
-    def jit_call(self, label, cpu, _vmmngr, breakpoints):
-        """Call the function label with cpu and vmmngr states
-        @label: function's label
-        @cpu: JitCpu instance
-        @breakpoints: Dict instance of used breakpoints
-        """
-        return self.exec_wrapper(label, cpu, self.lbl2jitbloc.data, breakpoints,
-                                 self.options["max_exec_per_call"])
-
-    def runbloc(self, cpu, vm, lbl, breakpoints):
+    def runbloc(self, cpu, lbl, breakpoints):
         """Run the bloc starting at lbl.
         @cpu: JitCpu instance
-        @vm: VmMngr instance
         @lbl: target label
         """
 
         if lbl is None:
-            lbl = cpu.get_gpreg()[self.ir_arch.pc.name]
+            lbl = getattr(cpu, self.ir_arch.pc.name)
 
         if not lbl in self.lbl2jitbloc:
             # Need to JiT the bloc
-            self.disbloc(lbl, vm)
+            self.disbloc(lbl, cpu.vmmngr)
 
         # Run the bloc and update cpu/vmmngr state
-        ret = self.jit_call(lbl, cpu, vm, breakpoints)
-
-        return ret
+        return self.exec_wrapper(lbl, cpu, self.lbl2jitbloc.data, breakpoints,
+                                 self.options["max_exec_per_call"])
 
     def blocs2memrange(self, blocs):
         """Return an interval instance standing for blocs addresses
diff --git a/miasm2/jitter/jitcore_cc_base.py b/miasm2/jitter/jitcore_cc_base.py
index baebc294..2c2d3d52 100644
--- a/miasm2/jitter/jitcore_cc_base.py
+++ b/miasm2/jitter/jitcore_cc_base.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import os
diff --git a/miasm2/jitter/jitcore_gcc.py b/miasm2/jitter/jitcore_gcc.py
index 0d9d5778..ccccc37a 100644
--- a/miasm2/jitter/jitcore_gcc.py
+++ b/miasm2/jitter/jitcore_gcc.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 import os
diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py
index 0f265073..8f58f1da 100644
--- a/miasm2/jitter/jitcore_llvm.py
+++ b/miasm2/jitter/jitcore_llvm.py
@@ -1,6 +1,7 @@
 import os
 import importlib
-import hashlib
+import tempfile
+from hashlib import md5
 from miasm2.jitter.llvmconvert import *
 import miasm2.jitter.jitcore as jitcore
 import Jitllvm
@@ -28,9 +29,18 @@ class JitCore_LLVM(jitcore.JitCore):
                              })
 
         self.exec_wrapper = Jitllvm.llvm_exec_bloc
-        self.exec_engines = []
         self.ir_arch = ir_arch
 
+        # Cache temporary dir
+        self.tempdir = os.path.join(tempfile.gettempdir(), "miasm_cache")
+        try:
+            os.mkdir(self.tempdir, 0755)
+        except OSError:
+            pass
+        if not os.access(self.tempdir, os.R_OK | os.W_OK):
+            raise RuntimeError(
+                'Cannot access cache directory %s ' % self.tempdir)
+
     def load(self):
 
         # Library to load within Jit context
@@ -60,43 +70,62 @@ class JitCore_LLVM(jitcore.JitCore):
         mod = importlib.import_module(mod_name)
         self.context.set_vmcpu(mod.get_gpreg_offset_all())
 
+        # Enable caching
+        self.context.enable_cache()
+
     def add_bloc(self, block):
         """Add a block to JiT and JiT it.
         @block: the block to add
         """
-        # TODO: caching using hash
+        block_hash = self.hash_block(block)
+        fname_out = os.path.join(self.tempdir, "%s.bc" % block_hash)
 
-        # Build a function in the context
-        func = LLVMFunction(self.context, block.label.name)
+        if not os.access(fname_out, os.R_OK):
+            # Build a function in the context
+            func = LLVMFunction(self.context, block.label.name)
 
-        # Set log level
-        func.log_regs = self.log_regs
-        func.log_mn = self.log_mn
+            # Set log level
+            func.log_regs = self.log_regs
+            func.log_mn = self.log_mn
 
-        # Import asm block
-        func.from_asmblock(block)
+            # Import asm block
+            func.from_asmblock(block)
 
-        # Verify
-        if self.options["safe_mode"] is True:
-            func.verify()
+            # Verify
+            if self.options["safe_mode"] is True:
+                func.verify()
 
-        # Optimise
-        if self.options["optimise"] is True:
-            func.optimise()
+            # 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()
+            # Log
+            if self.options["log_func"] is True:
+                print func
+            if self.options["log_assembly"] is True:
+                print func.get_assembly()
+
+            # Use propagate the cache filename
+            self.context.set_cache_filename(func, fname_out)
+
+            # Get a pointer on the function for JiT
+            ptr = func.get_function_pointer()
+
+        else:
+            # The cache file exists: function can be loaded from cache
+            ptr = self.context.get_ptr_from_cache(fname_out, block.label.name)
 
         # Store a pointer on the function jitted code
-        self.lbl2jitbloc[block.label.offset] = func.get_function_pointer()
+        self.lbl2jitbloc[block.label.offset] = ptr
 
-    def jit_call(self, label, cpu, _vmmngr, breakpoints):
-        """Call the function label with cpu and vmmngr states
-        @label: function's label
-        @cpu: JitCpu instance
-        @breakpoints: Dict instance of used breakpoints
+    def hash_block(self, block):
+        """
+        Build a hash of the block @block
+        @block: asmbloc
         """
-        return self.exec_wrapper(self.lbl2jitbloc[label], cpu, cpu.vmmngr.vmmngr)
+        block_raw = "".join(line.b for line in block.lines)
+        block_hash = md5("%X_%s_%s_%s" % (block.label.offset,
+                                          self.log_mn,
+                                          self.log_regs,
+                                          block_raw)).hexdigest()
+        return block_hash
diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py
index 87259f71..27666ab4 100644
--- a/miasm2/jitter/jitcore_python.py
+++ b/miasm2/jitter/jitcore_python.py
@@ -38,11 +38,12 @@ class JitCore_Python(jitcore.JitCore):
         @irblocs: a gorup of irblocs
         """
 
-        def myfunc(cpu, vmmngr):
+        def myfunc(cpu):
             """Execute the function according to cpu and vmmngr states
             @cpu: JitCpu instance
-            @vm: VmMngr instance
             """
+            # Get virtual memory handler
+            vmmngr = cpu.vmmngr
 
             # Keep current location in irblocs
             cur_label = label
@@ -125,15 +126,15 @@ class JitCore_Python(jitcore.JitCore):
         # Associate myfunc with current label
         self.lbl2jitbloc[label.offset] = myfunc
 
-    def jit_call(self, label, cpu, vmmngr, _breakpoints):
-        """Call the function label with cpu and vmmngr states
+    def exec_wrapper(self, label, cpu, _lbl2jitbloc, _breakpoints,
+                     _max_exec_per_call):
+        """Call the function @label with @cpu
         @label: function's label
         @cpu: JitCpu instance
-        @vm: VmMngr instance
         """
 
         # Get Python function corresponding to @label
         fc_ptr = self.lbl2jitbloc[label]
 
         # Execute the function
-        return fc_ptr(cpu, vmmngr)
+        return fc_ptr(cpu)
diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py
index 1ab7df4d..5b47bf6d 100644
--- a/miasm2/jitter/jitcore_tcc.py
+++ b/miasm2/jitter/jitcore_tcc.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 import os
 import tempfile
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index b2416fd5..bc09e1f2 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 
 import logging
 from functools import wraps
@@ -297,7 +296,7 @@ class jitter:
         """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, self.breakpoints_handler.callbacks)
+        return self.jit.runbloc(self.cpu, pc, self.breakpoints_handler.callbacks)
 
     def runiter_once(self, pc):
         """Iterator on callbacks results on code running from PC.
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index 08b1986b..4031d8f2 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -11,6 +11,7 @@
 #
 #
 
+import os
 from llvmlite import binding as llvm
 from llvmlite import ir as llvm_ir
 import miasm2.expression.expression as m2_expr
@@ -228,6 +229,9 @@ class LLVMContext_JIT(LLVMContext):
                                    "args": [p8,
                                             itype,
                                             itype]}})
+        self.add_fc({"cpuid": {"ret": itype,
+                               "args": [itype,
+                                        itype]}})
 
         for k in [8, 16]:
             self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.IntType(k),
@@ -291,6 +295,57 @@ class LLVMContext_JIT(LLVMContext):
                               value])
 
 
+    @staticmethod
+    def cache_notify(module, buffer):
+        """Called when @module has been compiled to @buffer"""
+        if not hasattr(module, "fname_out"):
+            return
+        fname_out = module.fname_out
+
+        if os.access(fname_out, os.R_OK):
+            # No need to overwrite
+            return
+
+        open(fname_out, "w").write(buffer)
+
+    @staticmethod
+    def cache_getbuffer(module):
+        """Return a compiled buffer for @module if available"""
+        if not hasattr(module, "fname_out"):
+            return None
+
+        fname_out = module.fname_out
+        if os.access(fname_out, os.R_OK):
+            return open(fname_out).read()
+        return None
+
+    def enable_cache(self):
+        "Enable cache of compiled object"
+        # Load shared libraries
+        for lib_fname in self.library_filenames:
+            self.add_shared_library(lib_fname)
+
+        # Activate cache
+        self.exec_engine.set_object_cache(self.cache_notify,
+                                          self.cache_getbuffer)
+
+    def set_cache_filename(self, func, fname_out):
+        "Set the filename @fname_out to use for cache for @func"
+        # Use a custom attribute to propagate the cache filename
+        func.as_llvm_mod().fname_out = fname_out
+
+    def get_ptr_from_cache(self, file_name, func_name):
+        "Load @file_name and return a pointer on the jitter @func_name"
+        # We use an empty module to avoid loosing time on function building
+        empty_module = llvm.parse_assembly("")
+        empty_module.fname_out = file_name
+
+        engine = self.exec_engine
+        engine.add_module(empty_module)
+        engine.finalize_object()
+        return engine.get_function_address(func_name)
+
+
 class LLVMContext_IRCompilation(LLVMContext):
 
     """Extend LLVMContext in order to handle memory management and custom
@@ -327,6 +382,7 @@ class LLVMFunction():
     # Operation translation
     ## Basics
     op_translate = {'parity': 'parity',
+                    'cpuid': 'cpuid',
     }
     ## Add the size as first argument
     op_translate_with_size = {'<<<': 'rot_left',
@@ -418,9 +474,13 @@ class LLVMFunction():
         ptr = builder.gep(self.local_vars["vmcpu"],
                           [llvm_ir.Constant(LLVMType.IntType(),
                                             offset)])
-        int_size = LLVMType.IntType(expr.size)
+        regs = self.llvm_context.ir_arch.arch.regs
+        if hasattr(regs, "float_list") and expr in regs.float_list:
+            pointee_type = llvm_ir.DoubleType()
+        else:
+            pointee_type = LLVMType.IntType(expr.size)
         ptr_casted = builder.bitcast(ptr,
-                                     llvm_ir.PointerType(int_size))
+                                     llvm_ir.PointerType(pointee_type))
         # Store in cache
         self.local_vars_pointers[name] = ptr_casted
 
@@ -702,6 +762,20 @@ class LLVMFunction():
                 self.update_cache(expr, ret)
                 return ret
 
+            if op in ["int_16_to_double", "int_32_to_double", "int_64_to_double",
+                      "mem_16_to_double", "mem_32_to_double", "mem_64_to_double"]:
+                arg = self.add_ir(expr.args[0])
+                ret = builder.uitofp(arg, llvm_ir.DoubleType())
+                self.update_cache(expr, ret)
+                return ret
+
+            if op in ["double_to_int_16", "double_to_int_32", "double_to_int_64",
+                      "double_to_mem_16", "double_to_mem_32", "double_to_mem_64"]:
+                arg = self.add_ir(expr.args[0])
+                ret = builder.fptoui(arg, llvm_ir.IntType(expr.size))
+                self.update_cache(expr, ret)
+                return ret
+
             if len(expr.args) > 1:
 
                 if op == "*":
@@ -718,6 +792,10 @@ class LLVMFunction():
                     callback = builder.urem
                 elif op == "/":
                     callback = builder.udiv
+                elif op == "fadd":
+                    callback = builder.fadd
+                elif op == "fdiv":
+                    callback = builder.fdiv
                 else:
                     raise NotImplementedError('Unknown op: %s' % op)
 
diff --git a/miasm2/os_dep/linux_stdlib.py b/miasm2/os_dep/linux_stdlib.py
index 542af25f..b05b2cd9 100644
--- a/miasm2/os_dep/linux_stdlib.py
+++ b/miasm2/os_dep/linux_stdlib.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 from sys import stdout
diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py
index 3b2fdfaa..9d37c9b1 100644
--- a/miasm2/os_dep/win_api_x86_32_seh.py
+++ b/miasm2/os_dep/win_api_x86_32_seh.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 #-*- coding:utf-8 -*-
 
 #
diff --git a/test/arch/aarch64/unit/asm_test.py b/test/arch/aarch64/unit/asm_test.py
index a9e6cfc6..cfb2a81c 100644
--- a/test/arch/aarch64/unit/asm_test.py
+++ b/test/arch/aarch64/unit/asm_test.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 import sys
 import os
 
@@ -10,13 +9,6 @@ from miasm2.core import asmbloc
 from elfesteem.strpatchwork import StrPatchwork
 from miasm2.analysis.machine import Machine
 from miasm2.jitter.csts import *
-from pdb import pm
-
-
-filename = os.environ.get('PYTHONSTARTUP')
-if filename and os.path.isfile(filename):
-    execfile(filename)
-
 
 reg_and_id = dict(mn_aarch64.regs.all_regs_ids_byname)
 
diff --git a/test/arch/aarch64/unit/mn_ubfm.py b/test/arch/aarch64/unit/mn_ubfm.py
index 6f1857fb..25d1cde7 100644..100755
--- a/test/arch/aarch64/unit/mn_ubfm.py
+++ b/test/arch/aarch64/unit/mn_ubfm.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test
diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py
index 922642d3..3695fd29 100644..100755
--- a/test/arch/arm/sem.py
+++ b/test/arch/arm/sem.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/arch/mips32/unit/asm_test.py b/test/arch/mips32/unit/asm_test.py
index 7272c15e..35d87d85 100644
--- a/test/arch/mips32/unit/asm_test.py
+++ b/test/arch/mips32/unit/asm_test.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 import sys
 import os
 
@@ -10,17 +9,10 @@ from miasm2.core import asmbloc
 from elfesteem.strpatchwork import StrPatchwork
 from miasm2.analysis.machine import Machine
 from miasm2.jitter.csts import *
-from pdb import pm
-
-
-filename = os.environ.get('PYTHONSTARTUP')
-if filename and os.path.isfile(filename):
-    execfile(filename)
 
 
 reg_and_id = dict(mn_mips32.regs.all_regs_ids_byname)
 
-
 class Asm_Test(object):
 
     def __init__(self, jitter):
diff --git a/test/arch/mips32/unit/mn_bcc.py b/test/arch/mips32/unit/mn_bcc.py
index 4818c171..e9b28e77 100644..100755
--- a/test/arch/mips32/unit/mn_bcc.py
+++ b/test/arch/mips32/unit/mn_bcc.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test
diff --git a/test/arch/msp430/sem.py b/test/arch/msp430/sem.py
index 4d39d357..433055e0 100644..100755
--- a/test/arch/msp430/sem.py
+++ b/test/arch/msp430/sem.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/arch/x86/sem.py b/test/arch/x86/sem.py
index 93d2ff83..d2198847 100644..100755
--- a/test/arch/x86/sem.py
+++ b/test/arch/x86/sem.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 # Loosely based on ARM's sem.py
diff --git a/test/arch/x86/unit/asm_test.py b/test/arch/x86/unit/asm_test.py
index 4e1d03b8..bf97dbe4 100644
--- a/test/arch/x86/unit/asm_test.py
+++ b/test/arch/x86/unit/asm_test.py
@@ -1,4 +1,3 @@
-#! /usr/bin/env python
 import sys
 import os
 
@@ -10,13 +9,6 @@ from miasm2.core import asmbloc
 from elfesteem.strpatchwork import StrPatchwork
 from miasm2.analysis.machine import Machine
 from miasm2.jitter.csts import *
-from pdb import pm
-
-
-filename = os.environ.get('PYTHONSTARTUP')
-if filename and os.path.isfile(filename):
-    execfile(filename)
-
 
 reg_and_id = dict(mn_x86.regs.all_regs_ids_byname)
 
diff --git a/test/arch/x86/unit/mn_daa.py b/test/arch/x86/unit/mn_daa.py
index d07bf849..21d609e4 100644..100755
--- a/test/arch/x86/unit/mn_daa.py
+++ b/test/arch/x86/unit/mn_daa.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_das.py b/test/arch/x86/unit/mn_das.py
index 2d8102d9..08df1a7a 100644..100755
--- a/test/arch/x86/unit/mn_das.py
+++ b/test/arch/x86/unit/mn_das.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_float.py b/test/arch/x86/unit/mn_float.py
index d704de73..f31a25e3 100644..100755
--- a/test/arch/x86/unit/mn_float.py
+++ b/test/arch/x86/unit/mn_float.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_int.py b/test/arch/x86/unit/mn_int.py
index 9d964220..09792371 100644..100755
--- a/test/arch/x86/unit/mn_int.py
+++ b/test/arch/x86/unit/mn_int.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from miasm2.jitter.csts import EXCEPT_INT_XX
diff --git a/test/arch/x86/unit/mn_pcmpeq.py b/test/arch/x86/unit/mn_pcmpeq.py
index 5d0a59c6..22760db4 100644..100755
--- a/test/arch/x86/unit/mn_pcmpeq.py
+++ b/test/arch/x86/unit/mn_pcmpeq.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pextr.py b/test/arch/x86/unit/mn_pextr.py
index 696f077b..c4548d67 100644..100755
--- a/test/arch/x86/unit/mn_pextr.py
+++ b/test/arch/x86/unit/mn_pextr.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pinsr.py b/test/arch/x86/unit/mn_pinsr.py
index 74120e5c..4beaba13 100644..100755
--- a/test/arch/x86/unit/mn_pinsr.py
+++ b/test/arch/x86/unit/mn_pinsr.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pmaxu.py b/test/arch/x86/unit/mn_pmaxu.py
index 527b966f..752b9132 100644..100755
--- a/test/arch/x86/unit/mn_pmaxu.py
+++ b/test/arch/x86/unit/mn_pmaxu.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pminu.py b/test/arch/x86/unit/mn_pminu.py
index d667df4e..3be95a9a 100644..100755
--- a/test/arch/x86/unit/mn_pminu.py
+++ b/test/arch/x86/unit/mn_pminu.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pmovmskb.py b/test/arch/x86/unit/mn_pmovmskb.py
index b7e7b897..a3eb65f5 100644..100755
--- a/test/arch/x86/unit/mn_pmovmskb.py
+++ b/test/arch/x86/unit/mn_pmovmskb.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pshufb.py b/test/arch/x86/unit/mn_pshufb.py
index 5f4c7370..d10c18e3 100644..100755
--- a/test/arch/x86/unit/mn_pshufb.py
+++ b/test/arch/x86/unit/mn_pshufb.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_psrl_psll.py b/test/arch/x86/unit/mn_psrl_psll.py
index 44126b96..a5428dab 100644..100755
--- a/test/arch/x86/unit/mn_psrl_psll.py
+++ b/test/arch/x86/unit/mn_psrl_psll.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_punpck.py b/test/arch/x86/unit/mn_punpck.py
index f6a4772e..b519b4c3 100644..100755
--- a/test/arch/x86/unit/mn_punpck.py
+++ b/test/arch/x86/unit/mn_punpck.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_pushpop.py b/test/arch/x86/unit/mn_pushpop.py
index 1a3f5517..ffcc3fa5 100644..100755
--- a/test/arch/x86/unit/mn_pushpop.py
+++ b/test/arch/x86/unit/mn_pushpop.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_16, Asm_Test_32
diff --git a/test/arch/x86/unit/mn_seh.py b/test/arch/x86/unit/mn_seh.py
index d6fc56ca..dd3fd4ef 100644..100755
--- a/test/arch/x86/unit/mn_seh.py
+++ b/test/arch/x86/unit/mn_seh.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from miasm2.os_dep.win_api_x86_32_seh import fake_seh_handler, build_teb, \
diff --git a/test/arch/x86/unit/mn_stack.py b/test/arch/x86/unit/mn_stack.py
index 3bce3979..f9cfc60a 100644..100755
--- a/test/arch/x86/unit/mn_stack.py
+++ b/test/arch/x86/unit/mn_stack.py
@@ -1,4 +1,5 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
+
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/arch/x86/unit/mn_strings.py b/test/arch/x86/unit/mn_strings.py
index 5e7269f7..3cb70e2a 100644..100755
--- a/test/arch/x86/unit/mn_strings.py
+++ b/test/arch/x86/unit/mn_strings.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python2
 import sys
 
 from asm_test import Asm_Test_32
diff --git a/test/core/interval.py b/test/core/interval.py
index 4572ac50..ab18e567 100644..100755
--- a/test/core/interval.py
+++ b/test/core/interval.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 from miasm2.core.interval import *
diff --git a/test/core/parse_asm.py b/test/core/parse_asm.py
index a488d075..e91c8c8c 100644..100755
--- a/test/core/parse_asm.py
+++ b/test/core/parse_asm.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/core/test_types.py b/test/core/test_types.py
index f6e5cb13..ab1d47c4 100644..100755
--- a/test/core/test_types.py
+++ b/test/core/test_types.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 
 # miasm2.core.types tests
 
diff --git a/test/core/utils.py b/test/core/utils.py
index f7de6565..b506f904 100644..100755
--- a/test/core/utils.py
+++ b/test/core/utils.py
@@ -1,4 +1,5 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
+
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/expression/expression_helper.py b/test/expression/expression_helper.py
index a3a8fba4..6c800020 100644..100755
--- a/test/expression/expression_helper.py
+++ b/test/expression/expression_helper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/expression/stp.py b/test/expression/stp.py
index fe09e865..b911a2a4 100644..100755
--- a/test/expression/stp.py
+++ b/test/expression/stp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/ir/analysis.py b/test/ir/analysis.py
index 913d9c56..913d9c56 100755..100644
--- a/test/ir/analysis.py
+++ b/test/ir/analysis.py
diff --git a/test/ir/ir2C.py b/test/ir/ir2C.py
index 36683904..395703ed 100644..100755
--- a/test/ir/ir2C.py
+++ b/test/ir/ir2C.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py
index 24b02341..2e776f74 100644..100755
--- a/test/ir/symbexec.py
+++ b/test/ir/symbexec.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/jitter/jit_options.py b/test/jitter/jit_options.py
new file mode 100644
index 00000000..cc955c64
--- /dev/null
+++ b/test/jitter/jit_options.py
@@ -0,0 +1,97 @@
+import os
+import sys
+from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
+from miasm2.analysis.machine import Machine
+from pdb import pm
+
+# Shellcode
+
+# main:
+#       MOV EAX, 0x1
+# loop_main:
+#       CMP EAX, 0x10
+#       JZ loop_end
+# loop_inc:
+#       INC EAX
+#       JMP loop_main
+# loop_end:
+#       RET
+data = "b80100000083f810740340ebf8c3".decode("hex")
+run_addr = 0x40000000
+
+def code_sentinelle(jitter):
+    jitter.run = False
+    jitter.pc = 0
+    return True
+
+def init_jitter():
+    global data, run_addr
+    # Create jitter
+    myjit = Machine("x86_32").jitter(sys.argv[1])
+
+    myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, data)
+
+    # Init jitter
+    myjit.init_stack()
+    myjit.jit.log_regs = True
+    myjit.jit.log_mn = True
+    myjit.push_uint32_t(0x1337beef)
+
+    myjit.add_breakpoint(0x1337beef, code_sentinelle)
+    return myjit
+
+# Test 'max_exec_per_call'
+print "[+] First run, to jit blocks"
+myjit = init_jitter()
+myjit.init_run(run_addr)
+myjit.continue_run()
+
+assert myjit.run is False
+assert myjit.cpu.EAX  == 0x10
+
+## Let's specify a max_exec_per_call
+## 5: main, loop_main, loop_inc, loop_main, loop_inc
+myjit.jit.options["max_exec_per_call"] = 5
+
+first_call = True
+def cb(jitter):
+    global first_call
+    if first_call:
+        # Avoid breaking on the first pass (before any execution)
+        first_call = False
+        return True
+    return False
+
+## Second run
+print "[+] Second run"
+myjit.push_uint32_t(0x1337beef)
+myjit.cpu.EAX = 0
+myjit.init_run(run_addr)
+myjit.exec_cb = cb
+myjit.continue_run()
+
+assert myjit.run is True
+# Use a '<=' because it's a 'max_...'
+assert myjit.cpu.EAX <= 3
+
+# Test 'jit_maxline'
+print "[+] Run instr one by one"
+myjit = init_jitter()
+myjit.jit.options["jit_maxline"] = 1
+myjit.jit.options["max_exec_per_call"] = 1
+
+counter = 0
+def cb(jitter):
+    global counter
+    counter += 1
+    return True
+
+myjit.init_run(run_addr)
+myjit.exec_cb = cb
+myjit.continue_run()
+
+assert myjit.run is False
+assert myjit.cpu.EAX  == 0x10
+## dry(1) + main(1) + (loop_main(2) + loop_inc(2))*(0x10 - 1) + loop_main(2) +
+## loop_end(1) = 65
+assert counter == 65
diff --git a/test/jitter/jitload.py b/test/jitter/jitload.py
index 283298db..544e9d18 100644
--- a/test/jitter/jitload.py
+++ b/test/jitter/jitload.py
@@ -1,3 +1,4 @@
+import sys
 from pdb import pm
 
 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
@@ -9,7 +10,7 @@ from miasm2.expression.expression import ExprId, ExprInt32, ExprInt64, ExprAff,
 data = "8d49048d5b0180f90174058d5bffeb038d5b0189d8c3".decode("hex")
 
 # Init jitter
-myjit = Machine("x86_32").jitter()
+myjit = Machine("x86_32").jitter(sys.argv[1])
 myjit.init_stack()
 
 run_addr = 0x40000000
diff --git a/test/jitter/vm_mngr.py b/test/jitter/vm_mngr.py
index b2b7336b..87bc6f8f 100644
--- a/test/jitter/vm_mngr.py
+++ b/test/jitter/vm_mngr.py
@@ -1,7 +1,8 @@
+import sys
 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm2.analysis.machine import Machine
 
-myjit = Machine("x86_32").jitter()
+myjit = Machine("x86_32").jitter(sys.argv[1])
 
 base_addr = 0x13371337
 page_size = 0x1000
diff --git a/test/os_dep/win_api_x86_32.py b/test/os_dep/win_api_x86_32.py
index bb13138f..2e22ccea 100644..100755
--- a/test/os_dep/win_api_x86_32.py
+++ b/test/os_dep/win_api_x86_32.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#! /usr/bin/env python2
 #-*- coding:utf-8 -*-
 
 import unittest
diff --git a/test/test_all.py b/test/test_all.py
index 7cc8f6eb..59624832 100644..100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -1,3 +1,5 @@
+#! /usr/bin/env python2
+
 import argparse
 import time
 import os
@@ -55,7 +57,7 @@ class ArchUnitTest(RegressionTest):
 
 # script -> blacklisted jitter
 blacklist = {
-    "x86/unit/mn_float.py": ["python", "llvm"],
+    "x86/unit/mn_float.py": ["python"],
 }
 for script in ["x86/sem.py",
                "x86/unit/mn_strings.py",
@@ -323,8 +325,11 @@ for i, test_args in enumerate(test_args):
 ## Jitter
 for script in ["jitload.py",
                "vm_mngr.py",
+               "jit_options.py",
                ]:
-    testset += RegressionTest([script], base_dir="jitter", tags=[TAGS["tcc"]])
+    for engine in ArchUnitTest.jitter_engines:
+        testset += RegressionTest([script, engine], base_dir="jitter",
+                                  tags=[TAGS.get(engine,None)])
 
 
 # Examples