about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/aarch64/jit.py3
-rw-r--r--miasm2/arch/aarch64/sem.py3
-rw-r--r--miasm2/arch/arm/jit.py2
-rw-r--r--miasm2/arch/mips32/jit.py7
-rw-r--r--miasm2/arch/mips32/regs.py2
-rw-r--r--miasm2/arch/msp430/jit.py3
-rw-r--r--miasm2/arch/msp430/regs.py1
-rw-r--r--miasm2/arch/x86/jit.py3
-rw-r--r--miasm2/arch/x86/sem.py3
-rw-r--r--miasm2/ir/ir2C.py432
-rw-r--r--miasm2/jitter/JitCore.h2
-rw-r--r--miasm2/jitter/codegen.py567
-rw-r--r--miasm2/jitter/csts.py3
-rw-r--r--miasm2/jitter/jitcore.py9
-rw-r--r--miasm2/jitter/jitcore_gcc.py19
-rw-r--r--miasm2/jitter/jitcore_tcc.py19
-rw-r--r--miasm2/jitter/jitload.py8
-rw-r--r--test/test_all.py3
18 files changed, 615 insertions, 474 deletions
diff --git a/miasm2/arch/aarch64/jit.py b/miasm2/arch/aarch64/jit.py
index 44b0609f..ca8d7b39 100644
--- a/miasm2/arch/aarch64/jit.py
+++ b/miasm2/arch/aarch64/jit.py
@@ -11,7 +11,6 @@ hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
 log.setLevel(logging.CRITICAL)
 
-
 class jitter_aarch64l(jitter):
     max_reg_arg = 8
 
@@ -19,7 +18,6 @@ class jitter_aarch64l(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_aarch64l(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
 
     def push_uint64_t(self, v):
         self.cpu.SP -= 8
@@ -70,4 +68,3 @@ class jitter_aarch64b(jitter_aarch64l):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_aarch64b(sp), *args, **kwargs)
         self.vm.set_big_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index b198bc43..02a93dd2 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -793,7 +793,8 @@ class ir_aarch64l(ir):
                 dst = self.expr_fix_regs_for_mode(dst)
                 src = self.expr_fix_regs_for_mode(src)
                 assignblk[dst] = src
-        irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst)
+        if irbloc.dst is not None:
+            irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst)
 
     def mod_pc(self, instr, instr_ir, extra_ir):
         "Replace PC by the instruction's offset"
diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py
index a9b93f6b..70d16176 100644
--- a/miasm2/arch/arm/jit.py
+++ b/miasm2/arch/arm/jit.py
@@ -17,7 +17,6 @@ class jitter_arml(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_arml(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
 
     def push_uint32_t(self, v):
         self.cpu.SP -= 4
@@ -67,4 +66,3 @@ class jitter_armb(jitter_arml):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_armb(sp), *args, **kwargs)
         self.vm.set_big_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py
index 93223896..aca85de5 100644
--- a/miasm2/arch/mips32/jit.py
+++ b/miasm2/arch/mips32/jit.py
@@ -1,9 +1,10 @@
+import logging
+
 from miasm2.jitter.jitload import jitter
 from miasm2.core import asmbloc
 from miasm2.core.utils import *
 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b
-
-import logging
+from miasm2.jitter.codegen import CGen
 
 log = logging.getLogger('jit_mips32')
 hnd = logging.StreamHandler()
@@ -17,7 +18,6 @@ class jitter_mips32l(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_mips32l(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
 
     def push_uint32_t(self, v):
         self.cpu.SP -= 4
@@ -42,4 +42,3 @@ class jitter_mips32b(jitter_mips32l):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_mips32b(sp), *args, **kwargs)
         self.vm.set_big_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py
index 6ddcf25b..b64b40d5 100644
--- a/miasm2/arch/mips32/regs.py
+++ b/miasm2/arch/mips32/regs.py
@@ -11,6 +11,8 @@ gen_reg('PC_FETCH', globals())
 gen_reg('R_LO', globals())
 gen_reg('R_HI', globals())
 
+exception_flags = ExprId('exception_flags', 32)
+
 PC_init = ExprId("PC_init")
 PC_FETCH_init = ExprId("PC_FETCH_init")
 
diff --git a/miasm2/arch/msp430/jit.py b/miasm2/arch/msp430/jit.py
index 5a4ff58b..95d34f96 100644
--- a/miasm2/arch/msp430/jit.py
+++ b/miasm2/arch/msp430/jit.py
@@ -1,6 +1,7 @@
 from miasm2.jitter.jitload import jitter
 from miasm2.core import asmbloc
 from miasm2.core.utils import *
+from miasm2.arch.msp430.sem import ir_msp430
 
 import logging
 
@@ -13,11 +14,9 @@ log.setLevel(logging.CRITICAL)
 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.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC
 
     def push_uint16_t(self, v):
         regs = self.cpu.get_gpreg()
diff --git a/miasm2/arch/msp430/regs.py b/miasm2/arch/msp430/regs.py
index 60638f26..1e35029f 100644
--- a/miasm2/arch/msp430/regs.py
+++ b/miasm2/arch/msp430/regs.py
@@ -7,6 +7,7 @@ from miasm2.core.cpu import reg_info
 regs16_str = ["PC", "SP", "SR"] + ["R%d" % i for i in xrange(3, 16)]
 regs16_expr = [ExprId(x, 16) for x in regs16_str]
 
+exception_flags = ExprId('exception_flags', 32)
 
 gpregs = reg_info(regs16_str, regs16_expr)
 
diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py
index c4f6f128..771b651a 100644
--- a/miasm2/arch/x86/jit.py
+++ b/miasm2/arch/x86/jit.py
@@ -17,7 +17,6 @@ class jitter_x86_16(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_x86_16(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP
         self.ir_arch.do_stk_segm = False
         self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode
         self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode
@@ -49,7 +48,6 @@ class jitter_x86_32(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_x86_32(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP
         self.ir_arch.do_stk_segm = False
 
         self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode
@@ -109,7 +107,6 @@ class jitter_x86_64(jitter):
         sp = asmbloc.asm_symbol_pool()
         jitter.__init__(self, ir_x86_64(sp), *args, **kwargs)
         self.vm.set_little_endian()
-        self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP
         self.ir_arch.do_stk_segm = False
 
         self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 11da1e8b..cdc98fba 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -4571,7 +4571,8 @@ class ir_x86_16(ir):
                 dst = self.expr_fix_regs_for_mode(dst, mode)
                 src = self.expr_fix_regs_for_mode(src, mode)
                 assignblk[dst] = src
-        irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode)
+        if irbloc.dst is not None:
+            irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode)
 
 
 class ir_x86_32(ir_x86_16):
diff --git a/miasm2/ir/ir2C.py b/miasm2/ir/ir2C.py
deleted file mode 100644
index ebc61e27..00000000
--- a/miasm2/ir/ir2C.py
+++ /dev/null
@@ -1,432 +0,0 @@
-import miasm2.expression.expression as m2_expr
-from miasm2.expression.simplifications import expr_simp
-from miasm2.core import asmbloc
-from miasm2.ir.translators import Translator
-import logging
-
-
-log_to_c_h = logging.getLogger("ir_helper")
-console_handler = logging.StreamHandler()
-console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
-log_to_c_h.addHandler(console_handler)
-log_to_c_h.setLevel(logging.WARN)
-
-# Miasm to C translator
-translator = Translator.to_language("C")
-
-prefetch_id = []
-prefetch_id_size = {}
-for size in [8, 16, 32, 64]:
-    prefetch_id_size[size] = []
-    for i in xrange(20):
-        name = 'pfmem%.2d_%d' % (size, i)
-        c = m2_expr.ExprId(name, size)
-        globals()[name] = c
-        prefetch_id.append(c)
-        prefetch_id_size[size].append(c)
-
-def init_arch_C(arch):
-    arch.id2Cid = {}
-    for x in arch.regs.all_regs_ids + prefetch_id:
-        arch.id2Cid[x] = m2_expr.ExprId('mycpu->' + str(x), x.size)
-
-    arch.id2newCid = {}
-
-    for x in arch.regs.all_regs_ids + prefetch_id:
-        arch.id2newCid[x] = m2_expr.ExprId('mycpu->%s_new' % x, x.size)
-
-
-def patch_c_id(arch, e):
-    return e.replace_expr(arch.id2Cid)
-
-
-def patch_c_new_id(arch, e):
-    return e.replace_expr(arch.id2newCid)
-
-
-mask_int = 0xffffffffffffffff
-
-
-pre_instr_test_exception = r"""
-// pre instruction test exception
-if (VM_exception_flag) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-
-code_exception_fetch_mem_at_instr = r"""
-// except fetch mem at instr
-if (VM_exception_flag & EXCEPT_DO_NOT_UPDATE_PC) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-code_exception_fetch_mem_post_instr = r"""
-// except fetch mem post instr
-if (VM_exception_flag) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-
-code_exception_fetch_mem_at_instr_noautomod = r"""
-// except fetch mem at instr noauto
-if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-code_exception_fetch_mem_post_instr_noautomod = r"""
-// except post instr noauto
-if (VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-
-code_exception_at_instr = r"""
-// except at instr
-if (CPU_exception_flag && CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-code_exception_post_instr = r"""
-// except post instr
-if (CPU_exception_flag) {
-    if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
-      %s;
-    }
-    else {
-      %s;
-    }
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-
-code_exception_at_instr_noautomod = r"""
-if ((CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) && (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP)) {
-    %s;
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-code_exception_post_instr_noautomod = r"""
-if (CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) {
-    if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
-      %s;
-    }
-    else {
-      %s;
-    }
-    return JIT_RET_EXCEPTION;
-}
-"""
-
-goto_local_code = r"""
-if (BlockDst->is_local) {
-    goto *local_labels[BlockDst->address];
-}
-else {
-    return JIT_RET_NO_EXCEPTION;
-}
-"""
-
-my_size_mask = {1: 1, 2: 3, 3: 7, 7: 0x7f,
-                8: 0xFF,
-                16: 0xFFFF,
-                32: 0xFFFFFFFF,
-                64: 0xFFFFFFFFFFFFFFFFL}
-
-exception_flags = m2_expr.ExprId('exception_flags', 32)
-
-
-def set_pc(ir_arch, src):
-    dst = ir_arch.jit_pc
-    if not isinstance(src, m2_expr.Expr):
-        src = m2_expr.ExprInt_from(dst, src)
-    e = m2_expr.ExprAff(dst, src.zeroExtend(dst.size))
-    return e
-
-
-def gen_resolve_int(ir_arch, e):
-    return 'Resolve_dst(BlockDst, 0x%X, 0)' % (e.arg)
-
-def gen_resolve_id_lbl(ir_arch, e):
-    if e.name.name.startswith("lbl_gen_"):
-        # TODO XXX CLEAN
-        return 'Resolve_dst(BlockDst, 0x%X, 1)'%(e.name.index)
-    else:
-        return 'Resolve_dst(BlockDst, 0x%X, 0)'%(e.name.offset)
-
-def gen_resolve_id(ir_arch, e):
-    return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e)))
-
-def gen_resolve_mem(ir_arch, e):
-    return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e)))
-
-def gen_resolve_other(ir_arch, e):
-    return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e)))
-
-def gen_resolve_dst_simple(ir_arch, e):
-    if isinstance(e, m2_expr.ExprInt):
-        return gen_resolve_int(ir_arch, e)
-    elif isinstance(e, m2_expr.ExprId) and isinstance(e.name,
-                                                      asmbloc.asm_label):
-        return gen_resolve_id_lbl(ir_arch, e)
-    elif isinstance(e, m2_expr.ExprId):
-        return gen_resolve_id(ir_arch, e)
-    elif isinstance(e, m2_expr.ExprMem):
-        return gen_resolve_mem(ir_arch, e)
-    else:
-        return gen_resolve_other(ir_arch, e)
-
-
-def gen_irdst(ir_arch, e):
-    out = []
-    if isinstance(e, m2_expr.ExprCond):
-        dst_cond_c = translator.from_expr(patch_c_id(ir_arch.arch, e.cond))
-        out.append("if (%s)"%dst_cond_c)
-        out.append('    %s;'%(gen_resolve_dst_simple(ir_arch, e.src1)))
-        out.append("else")
-        out.append('    %s;'%(gen_resolve_dst_simple(ir_arch, e.src2)))
-    else:
-        out.append('%s;'%(gen_resolve_dst_simple(ir_arch, e)))
-    return out
-
-def Expr2C(ir_arch, l, assignblk, gen_exception_code=False):
-    id_to_update = []
-    out = ["// %s" % (l)]
-    out_pc = []
-
-    dst_dict = {}
-    src_mem = {}
-
-    prefect_index = {8: 0, 16: 0, 32: 0, 64: 0}
-    new_expr = []
-
-    pc_is_dst = False
-    fetch_mem = False
-    set_exception_flags = False
-    for dst, src in assignblk.iteritems():
-        assert not isinstance(dst, m2_expr.ExprOp)
-        if dst in dst_dict:
-            raise RuntimeError("warning: detected multi dst to same id")
-        new_expr.append((dst, src))
-        # test exception flags
-        ops = m2_expr.get_expr_ops(src)
-        if set(['umod', 'udiv']).intersection(ops):
-            set_exception_flags = True
-        if dst == exception_flags:
-            set_exception_flags = True
-            # TODO XXX test function whose set exception_flags
-
-        # search mem lookup for generate mem read prefetch
-        rs = src.get_r(mem_read=True)
-        for r in rs:
-            if (not isinstance(r, m2_expr.ExprMem)) or r in src_mem:
-                continue
-            fetch_mem = True
-            index = prefect_index[r.size]
-            prefect_index[r.size] += 1
-            pfmem = prefetch_id_size[r.size][index]
-            src_mem[r] = pfmem
-
-    out_mem = []
-
-    # first, generate mem prefetch
-    mem_k = src_mem.keys()
-    mem_k.sort()
-    for k in mem_k:
-        str_src = translator.from_expr(patch_c_id(ir_arch.arch, k))
-        str_dst = translator.from_expr(patch_c_id(ir_arch.arch, src_mem[k]))
-        out.append('%s = %s;' % (str_dst, str_src))
-    src_w_len = {}
-    for k, v in src_mem.items():
-        src_w_len[k] = v
-    for dst, src in new_expr:
-        # reload src using prefetch
-        src = src.replace_expr(src_w_len)
-        if dst is ir_arch.IRDst:
-            out += gen_irdst(ir_arch, src)
-            continue
-
-
-        str_src = translator.from_expr(patch_c_id(ir_arch.arch, src))
-        str_dst = translator.from_expr(patch_c_id(ir_arch.arch, dst))
-
-
-
-        if isinstance(dst, m2_expr.ExprId):
-            id_to_update.append(dst)
-            str_dst = patch_c_new_id(ir_arch.arch, dst)
-            if dst in ir_arch.arch.regs.regs_flt_expr:
-                # dont mask float affectation
-                out.append('%s = (%s);' % (str_dst, str_src))
-            else:
-                out.append('%s = (%s)&0x%X;' % (str_dst, str_src,
-                                                my_size_mask[src.size]))
-        elif isinstance(dst, m2_expr.ExprMem):
-            fetch_mem = True
-            str_dst = str_dst.replace('MEM_LOOKUP', 'MEM_WRITE')
-            out_mem.append('%s, %s);' % (str_dst[:-1], str_src))
-
-        if dst == ir_arch.arch.pc[ir_arch.attrib]:
-            pc_is_dst = True
-            out_pc += ["return JIT_RET_NO_EXCEPTION;"]
-
-    # if len(id_to_update) != len(set(id_to_update)):
-    # raise ValueError('Not implemented: multi dst to same id!', str([str(x)
-    # for x in exprs]))
-    out += out_mem
-
-    if gen_exception_code:
-        if fetch_mem:
-            e = set_pc(ir_arch, l.offset & mask_int)
-            s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-            s1 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
-            out.append(code_exception_fetch_mem_at_instr_noautomod % s1)
-        if set_exception_flags:
-            e = set_pc(ir_arch, l.offset & mask_int)
-            s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-            s1 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
-            out.append(code_exception_at_instr_noautomod % s1)
-
-    for i in id_to_update:
-        if i is ir_arch.IRDst:
-            continue
-        out.append('%s = %s;' %
-                   (patch_c_id(ir_arch.arch, i), patch_c_new_id(ir_arch.arch, i)))
-
-    post_instr = []
-    # test stop exec ####
-    if gen_exception_code:
-        if set_exception_flags:
-            if pc_is_dst:
-                post_instr.append("if (VM_exception_flag) { " +
-                    "/*pc = 0x%X; */return JIT_RET_EXCEPTION; }" % (l.offset))
-            else:
-                e = set_pc(ir_arch, l.offset & mask_int)
-                s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-                s1 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
-                e = set_pc(ir_arch, (l.offset + l.l) & mask_int)
-                s2 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-                s2 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%((l.offset + l.l) & mask_int)
-                post_instr.append(
-                    code_exception_post_instr_noautomod % (s1, s2))
-
-        if fetch_mem:
-            if l.additional_info.except_on_instr:
-                offset = l.offset
-            else:
-                offset = l.offset + l.l
-
-            e = set_pc(ir_arch, offset & mask_int)
-            s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-            s1 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%(offset & mask_int)
-            post_instr.append(
-                code_exception_fetch_mem_post_instr_noautomod % (s1))
-
-    # pc manip after all modifications
-    return out, post_instr, post_instr + out_pc
-
-
-def label2offset(e):
-    if not isinstance(e, m2_expr.ExprId):
-        return e
-    if not isinstance(e.name, asmbloc.asm_label):
-        return e
-    return m2_expr.ExprInt_from(e, e.name.offset)
-
-
-def expr2pyobj(arch, e):
-    if isinstance(e, m2_expr.ExprId):
-        if isinstance(e.name, asmbloc.asm_label):
-            src_c = 'PyString_FromStringAndSize("%s", %d)' % (
-                e.name.name, len(e.name.name))
-        else:
-            src_c = 'PyLong_FromUnsignedLongLong(%s)' % patch_c_id(arch, e)
-    else:
-        raise NotImplementedError('unknown type for e: %s' % type(e))
-    return src_c
-
-
-def ir2C(ir_arch, irbloc, lbl_done,
-    gen_exception_code=False, log_mn=False, log_regs=False):
-    out = []
-    # print "TRANS"
-    # print irbloc
-    out.append(["%s:" % irbloc.label.name])
-    #out.append(['printf("%s:\n");' % irbloc.label.name])
-    assert len(irbloc.irs) == len(irbloc.lines)
-    for l, assignblk in zip(irbloc.lines, irbloc.irs):
-        if l.offset not in lbl_done:
-            e = set_pc(ir_arch, l.offset & mask_int)
-            s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e))
-            s1 += ';\n    Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
-            out.append([pre_instr_test_exception % (s1)])
-            lbl_done.add(l.offset)
-
-            if log_regs:
-                out.append([r'dump_gpregs(jitcpu->cpu);'])
-
-            if log_mn:
-                out.append(['printf("%.8X %s\\n");' % (l.offset, str(l))])
-        # print l
-        # gen pc update
-        post_instr = ""
-        c_code, post_instr, _ = Expr2C(ir_arch, l, assignblk, gen_exception_code)
-        out.append(c_code + post_instr)
-    out.append([goto_local_code ] )
-    return out
-
-
-def irblocs2C(ir_arch, resolvers, label, irblocs,
-    gen_exception_code=False, log_mn=False, log_regs=False):
-    out = []
-
-    lbls = [b.label for b in irblocs]
-    lbls_local = []
-    for l in lbls:
-        if l.name.startswith('lbl_gen_'):
-            l.index = int(l.name[8:], 16)
-            lbls_local.append(l)
-    lbl_index_min = 0
-    lbls_index = [l.index for l in lbls if hasattr(l, 'index')]
-    lbls_local.sort(key=lambda x:x.index)
-
-    if lbls_index:
-        lbl_index_min = min(lbls_index)
-        for l in lbls_local:
-            l.index -= lbl_index_min
-
-    out.append("void* local_labels[] = {%s};"%(', '.join(["&&%s"%l.name for l in lbls_local])))
-    out.append("vm_cpu_t* mycpu = (vm_cpu_t*)jitcpu->cpu;")
-
-
-    out.append("goto %s;" % label.name)
-    bloc_labels = [x.label for x in irblocs]
-    assert label in bloc_labels
-
-    lbl_done = set([None])
-
-    for irbloc in irblocs:
-        # XXXX TEST
-        if irbloc.label.offset is None:
-            b_out = ir2C(ir_arch, irbloc, lbl_done, gen_exception_code)
-        else:
-            b_out = ir2C(
-                ir_arch, irbloc, lbl_done, gen_exception_code, log_mn, log_regs)
-        for exprs in b_out:
-            for l in exprs:
-                out.append(l)
-        out.append("")
-
-    return out
-
diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h
index bae5a417..6add6f37 100644
--- a/miasm2/jitter/JitCore.h
+++ b/miasm2/jitter/JitCore.h
@@ -132,7 +132,7 @@ PyObject* vm_get_mem(JitCpu *self, PyObject* args);
 
 #define VM_exception_flag (((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags)
 #define CPU_exception_flag (((vm_cpu_t*)jitcpu->cpu)->exception_flags)
-
+#define CPU_exception_flag_at_instr ((CPU_exception_flag) && ((CPU_exception_flag) > EXCEPT_NUM_UPDT_EIP))
 #define JIT_RET_EXCEPTION 1
 #define JIT_RET_NO_EXCEPTION 0
 
diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py
new file mode 100644
index 00000000..c1f1e392
--- /dev/null
+++ b/miasm2/jitter/codegen.py
@@ -0,0 +1,567 @@
+import miasm2.expression.expression as m2_expr
+from miasm2.ir.ir import irbloc
+from miasm2.ir.translators import Translator
+from miasm2.core.asmbloc import expr_is_label, asm_block_bad, asm_label
+
+# Miasm to C translator
+translator = Translator.to_language("C")
+
+PREFETCH_ID = []
+PREFETCH_ID_SIZE = {}
+for size in [8, 16, 32, 64]:
+    PREFETCH_ID_SIZE[size] = []
+    for i in xrange(20):
+        name = 'pfmem%.2d_%d' % (size, i)
+        c = m2_expr.ExprId(name, size)
+        # globals()[name] = c
+        PREFETCH_ID.append(c)
+        PREFETCH_ID_SIZE[size].append(c)
+
+SIZE_TO_MASK = {x: 2**x - 1 for x in (1, 2, 3, 7, 8, 16, 32, 64)}
+
+MASK_INT = 0xffffffffffffffff
+
+
+class Attributes(object):
+
+    """
+    Store an irblock attributes
+    """
+
+    def __init__(self, log_mn=False, log_regs=False):
+        self.mem_read = False
+        self.mem_write = False
+        self.set_exception = False
+        self.op_set_exception = False
+        self.log_mn = log_mn
+        self.log_regs = log_regs
+        self.instr = None
+
+
+class CGen(object):
+
+    IMPLICIT_EXCEPTION_OP = set(['umod', 'udiv'])
+
+    """
+    Translate native assembly block to C
+    """
+
+    CODE_EXCEPTION_MEM_AT_INSTR = r"""
+    // except fetch mem at instr noauto
+    if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) {
+        %s = %s;
+        BlockDst->address = %s;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_EXCEPTION_MEM_POST_INSTR = r"""
+    // except fetch mem post instr
+    if (VM_exception_flag) {
+        %s = %s;
+        BlockDst->address = %s;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_EXCEPTION_AT_INSTR = r"""
+    if (CPU_exception_flag_at_instr) {
+        %s = %s;
+        BlockDst->address = %s;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_EXCEPTION_POST_INSTR = r"""
+    if (CPU_exception_flag) {
+        %s = %s;
+        BlockDst->address = %s;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_RETURN_EXCEPTION = r"""
+    return JIT_RET_EXCEPTION;
+    """
+
+    CODE_RETURN_NO_EXCEPTION = r"""
+    %s:
+    %s = %s;
+    BlockDst->address = %s;
+    return JIT_RET_NO_EXCEPTION;
+    """
+
+    CODE_CPU_EXCEPTION_POST_INSTR = r"""
+    if (CPU_exception_flag) {
+        %s = %s;
+        BlockDst->address = DST_value;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_VM_EXCEPTION_POST_INSTR = r"""
+    if (VM_exception_flag) {
+        %s = %s;
+        BlockDst->address = DST_value;
+        return JIT_RET_EXCEPTION;
+    }
+    """
+
+    CODE_INIT = r"""
+    int DST_case;
+    unsigned long long DST_value;
+    vm_cpu_t* mycpu = (vm_cpu_t*)jitcpu->cpu;
+
+    goto %s;
+    """
+
+    CODE_BAD_BLOCK = r"""
+    // Unknown mnemonic
+    CPU_exception_flag = EXCEPT_UNK_MNEMO;
+    """ + CODE_RETURN_EXCEPTION
+
+    def __init__(self, ir_arch):
+        self.ir_arch = ir_arch
+        self.PC = self.ir_arch.pc
+        self.init_arch_C()
+
+    def init_arch_C(self):
+        self.id_to_c_id = {}
+        for reg in self.ir_arch.arch.regs.all_regs_ids + PREFETCH_ID:
+            self.id_to_c_id[reg] = m2_expr.ExprId('mycpu->%s' % reg, reg.size)
+
+        self.id_to_new_c_id = {}
+
+        for reg in self.ir_arch.arch.regs.all_regs_ids + PREFETCH_ID:
+            self.id_to_new_c_id[reg] = m2_expr.ExprId(
+                'mycpu->%s_new' % reg, reg.size)
+
+        self.C_PC = self.id_to_c(self.PC)
+
+    def dst_to_c(self, src):
+        if not isinstance(src, m2_expr.Expr):
+            src = m2_expr.ExprInt(src, self.PC.size)
+        return self.id_to_c(src)
+
+    def patch_c_id(self, expr):
+        return expr.replace_expr(self.id_to_c_id)
+
+    def patch_c_new_id(self, expr):
+        return expr.replace_expr(self.id_to_new_c_id)
+
+    def id_to_c(self, expr):
+        return translator.from_expr(self.patch_c_id(expr))
+
+    def id_to_cnew(self, expr):
+        return translator.from_expr(self.patch_c_new_id(expr))
+
+    def get_post_instr_label(self, offset):
+        return self.ir_arch.symbol_pool.getby_name_create("lbl_gen_post_instr_%.8X" % (offset))
+
+    def add_label_index(self, dst2index, lbl):
+        dst2index[lbl] = len(dst2index)
+
+    def assignblk_to_irbloc(self, instr, assignblk):
+        """
+        Ensure IRDst is always set in the head @assignblk of the @instr
+        @assignblk: Assignblk instance
+        @instr: an instruction instance
+        """
+        if self.ir_arch.IRDst not in assignblk:
+            assignblk[self.ir_arch.IRDst] = m2_expr.ExprInt(
+                instr.offset + instr.l,
+                self.ir_arch.IRDst.size)
+
+        return irbloc(self.ir_arch.get_instr_label(instr), [assignblk])
+
+    def block2assignblks(self, block):
+        irblocks_list = []
+        for instr in block.lines:
+            assignblk_head, assignblks_extra = self.ir_arch.instr2ir(instr)
+            # Keep result in ordered list as first element is the assignblk head
+            # The remainings order is not really important
+            irblock_head = self.assignblk_to_irbloc(instr, assignblk_head)
+            irblocks = [irblock_head] + assignblks_extra
+
+            for irblock in irblocks:
+                assert irblock.dst is not None
+            irblocks_list.append(irblocks)
+        return irblocks_list
+
+    def gen_mem_prefetch(self, assignblk, mems_to_prefetch):
+        out = []
+        for expr, prefetcher in sorted(mems_to_prefetch.iteritems()):
+            str_src = self.id_to_c(expr)
+            str_dst = self.id_to_c(prefetcher)
+            out.append('%s = %s;' % (str_dst, str_src))
+        assignblk.C_prefetch = out
+        return out
+
+    def gen_assignments(self, assignblk, prefetchers):
+        out_main = []
+        out_mem = []
+        out_updt = []
+        id_to_update = set()
+
+        for dst, src in sorted(assignblk.iteritems()):
+            src = src.replace_expr(prefetchers)
+            if dst is self.ir_arch.IRDst:
+                pass
+            elif isinstance(dst, m2_expr.ExprId):
+                id_to_update.add(dst)
+                str_dst = self.id_to_cnew(dst)
+                if dst in self.ir_arch.arch.regs.regs_flt_expr:
+                    # Dont mask float affectation
+                    out_main.append('%s = (%s);' % (str_dst, self.id_to_c(src)))
+                else:
+                    out_main.append(
+                        '%s = (%s)&0x%X;' % (str_dst, self.id_to_c(src),
+                                             SIZE_TO_MASK[src.size]))
+            elif isinstance(dst, m2_expr.ExprMem):
+                ptr = dst.arg.replace_expr(prefetchers)
+                new_dst = m2_expr.ExprMem(ptr, dst.size)
+                str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE')
+                out_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src)))
+            else:
+                raise ValueError("Unknown dst")
+
+        for dst, new_dst in dst_var.iteritems():
+            if dst is self.ir_arch.IRDst:
+                continue
+            out_updt.append('%s = %s;' % (self.id_to_c(expr), self.id_to_cnew(expr)))
+
+        assignblk.C_main = out_main
+        assignblk.C_mem = out_mem
+        assignblk.C_updt = out_updt
+
+    def gen_c_assignblk(self, assignblk):
+        mem_read, mem_write = False, False
+        local_prefetch = {}
+        prefetch_index = {8: 0, 16: 0, 32: 0, 64: 0}
+
+        # Prefetch memory read
+        for expr in assignblk.get_r(mem_read=True):
+            if not isinstance(expr, m2_expr.ExprMem):
+                continue
+            mem_read = True
+            index = prefetch_index[expr.size]
+            prefetch_index[expr.size] += 1
+            local_prefetch[expr] = PREFETCH_ID_SIZE[expr.size][index]
+
+        # Check if assignblk can write mem
+        mem_write = any(isinstance(expr, m2_expr.ExprMem)
+                        for expr in assignblk.get_w())
+
+        assignblk.mem_write = mem_write
+        assignblk.mem_read = mem_read
+
+        # Generate memory prefetch
+        return local_prefetch
+
+    def gen_check_memory_exception(self, address):
+        dst = self.dst_to_c(address)
+        return (self.CODE_EXCEPTION_MEM_AT_INSTR % (self.C_PC, dst, dst)).split('\n')
+
+    def gen_check_memory_exception_post(self, address):
+        dst = self.dst_to_c(address)
+        return (self.CODE_EXCEPTION_MEM_POST_INSTR % (self.C_PC, dst, dst)).split('\n')
+
+    def gen_check_cpu_exception(self, address):
+        dst = self.dst_to_c(address)
+        return (self.CODE_EXCEPTION_AT_INSTR % (self.C_PC, dst, dst)).split('\n')
+
+    def gen_check_cpu_exception_post(self, address):
+        dst = self.dst_to_c(address)
+        return (self.CODE_EXCEPTION_POST_INSTR % (self.C_PC, dst, dst)).split('\n')
+
+    def traverse_expr_dst(self, expr, dst2index):
+        """
+        Generate the index of the destination label for the @expr
+        @dst2index: dictionnary to link label to its index
+        """
+
+        if isinstance(expr, m2_expr.ExprCond):
+            cond = self.id_to_c(expr.cond)
+            src1, src1b = self.traverse_expr_dst(expr.src1, dst2index)
+            src2, src2b = self.traverse_expr_dst(expr.src2, dst2index)
+            return ("((%s)?(%s):(%s))" % (cond, src1, src2),
+                    "((%s)?(%s):(%s))" % (cond, src1b, src2b))
+        elif isinstance(expr, m2_expr.ExprInt):
+            offset = int(expr.arg)
+            self.add_label_index(dst2index, offset)
+            return ("%s" % dst2index[offset],
+                    hex(offset))
+        elif expr_is_label(expr):
+            label = expr.name
+            if label.offset != None:
+                offset = label.offset
+                self.add_label_index(dst2index, offset)
+                return ("%s" % dst2index[offset],
+                        hex(offset))
+            else:
+                self.add_label_index(dst2index, label)
+                return ("%s" % dst2index[label],
+                        "0")
+
+        elif (isinstance(expr, m2_expr.ExprId) or
+              isinstance(expr, m2_expr.ExprMem) or
+              isinstance(expr, m2_expr.ExprSlice)):
+            dst2index[expr] = -1
+            return ("-1",
+                    self.id_to_c(expr))
+        else:
+            raise RuntimeError("Unsupported IRDst type %s" % expr)
+
+    def gen_assignblk_dst(self, dst):
+        dst2index = {}
+        (ret, retb) = self.traverse_expr_dst(dst, dst2index)
+        ret = "DST_case = %s;" % ret
+        retb = "DST_value = %s;" % retb
+        return ['// %s' % dst2index,
+                '%s' % ret,
+                '%s' % retb], dst2index
+
+    def gen_post_instr_checks(self, attrib, dst):
+        out = []
+        dst = self.dst_to_c(dst)
+        if attrib.mem_read | attrib.mem_write:
+            out += (self.CODE_VM_EXCEPTION_POST_INSTR % (self.C_PC, dst)).split('\n')
+        if attrib.set_exception or attrib.op_set_exception:
+            out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC, dst)).split('\n')
+
+        return out
+
+    def gen_pre_code(self, attrib):
+        out = []
+
+        if attrib.log_mn:
+            out.append('printf("%.8X %s\\n");' % (attrib.instr.offset,
+                                                  attrib.instr))
+        return out
+
+    def gen_post_code(self, attrib):
+        out = []
+        if attrib.log_regs:
+            out.append('dump_gpregs(jitcpu->cpu);')
+        return out
+
+    def gen_goto_code(self, attrib, instr_offsets, dst):
+        out = []
+        if isinstance(dst, asm_label):
+            out.append('goto %s;' % dst.name)
+        elif dst in instr_offsets:
+            lbl = self.ir_arch.symbol_pool.getby_offset_create(dst)
+            out += self.gen_post_code(attrib)
+            out += self.gen_post_instr_checks(attrib, dst)
+            out.append('goto %s;' % lbl.name)
+        else:
+            out += self.gen_post_code(attrib)
+            out.append('BlockDst->address = DST_value;')
+            out += self.gen_post_instr_checks(attrib, dst)
+            out.append('\t\treturn JIT_RET_NO_EXCEPTION;')
+        return out
+
+    def gen_dst_goto(self, attrib, instr_offsets, dst2index):
+        """
+        Generate code for possible @dst2index.
+
+        @attrib: an Attributs instance
+        @instr_offsets: list of instructions offsets
+        @dst2index: link from dstination to index
+        """
+
+        if not dst2index:
+            return []
+        out = []
+        out.append('switch(DST_case) {')
+        for dst, index in sorted(dst2index.iteritems(), key=lambda lblindex: lblindex[1]):
+            out.append('\tcase %d:' % index)
+            out += self.gen_goto_code(attrib, instr_offsets, dst)
+            out.append('\t\tbreak;')
+        out.append('};')
+        return out
+
+    def gen_c_code(self, assignblk, c_dst):
+        """
+        Generate the C code for @assignblk.
+        @assignblk: an Assignblk instance
+        @c_dst: irdst C code
+        """
+        out = []
+
+        out.append("// Prefetch")
+        out += assignblk.C_prefetch
+        out.append("// Dst")
+        out += c_dst
+        out.append("// Main")
+        out += assignblk.C_main
+
+        out.append("// Check op/mem exceptions")
+
+        # Check memory access if assignblk has memory read
+        if assignblk.C_prefetch:
+            out += self.gen_check_memory_exception(assignblk.instr_addr)
+
+        # Check if operator raised exception flags
+        if assignblk.op_set_exception:
+            out += self.gen_check_cpu_exception(assignblk.instr_addr)
+
+        out.append("// Mem updt")
+        out += assignblk.C_mem
+
+        out.append("// Check exception Mem write")
+        # Check memory write exceptions
+        if assignblk.mem_write:
+            out += self.gen_check_memory_exception(assignblk.instr_addr)
+
+        out.append("// Updt")
+        out += assignblk.C_updt
+
+        out.append("// Checks exception")
+
+        # Check post assignblk exception flags
+        if assignblk.set_exception:
+            out += self.gen_check_cpu_exception(assignblk.instr_addr)
+
+        return out
+
+    def is_exception_operator(self, operator):
+        """Return True if the @op operator can raise a runtime exception"""
+
+        return any(operator.startswith(except_op)
+                   for except_op in self.IMPLICIT_EXCEPTION_OP)
+
+    def get_caracteristics(self, irblock):
+        """
+        Get the carateristics of each assignblk in the @irblock
+        @irblock: an irbloc instance
+        """
+
+        for assignblk in irblock.irs:
+            assignblk.mem_read, assignblk.mem_write = False, False
+            assignblk.op_set_exception = False
+            # Check explicit exception raising
+            assignblk.set_exception = self.ir_arch.arch.regs.exception_flags in assignblk
+
+            element_read = assignblk.get_r(mem_read=True)
+            # Check implicit exception raising
+            assignblk.op_set_exception = any(self.is_exception_operator(operator)
+                                             for elem in assignblk.values()
+                                             for operator in m2_expr.get_expr_ops(elem))
+            # Check mem read
+            assignblk.mem_read = any(isinstance(expr, m2_expr.ExprMem)
+                                     for expr in element_read)
+            # Check mem write
+            assignblk.mem_write = any(isinstance(dst, m2_expr.ExprMem)
+                                      for dst in assignblk)
+
+    def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False):
+        """
+        Get the carateristics of each @irblocks. Returns the corresponding
+        attributes object.
+        @irblock: a list of irbloc instance
+        @log_mn: generate code to log instructions
+        @log_regs: generate code to log registers states
+        """
+
+        attrib = Attributes(log_mn, log_regs)
+
+        for irblock in irblocks:
+            for assignblk in irblock.irs:
+                self.get_caracteristics(irblock)
+                attrib.mem_read |= assignblk.mem_read
+                attrib.mem_write |= assignblk.mem_write
+                attrib.set_exception |= assignblk.set_exception
+                attrib.op_set_exception |= assignblk.op_set_exception
+        attrib.instr = instr
+        return attrib
+
+    def gen_bad_block(self):
+        """
+        Generate the C code for a bad_block instance
+        """
+        return self.CODE_BAD_BLOCK.split("\n")
+
+    def get_block_post_label(self, block):
+        last_instr = block.lines[-1]
+        offset = last_instr.offset + last_instr.l
+        return self.ir_arch.symbol_pool.getby_offset_create(offset)
+
+    def gen_init(self, block):
+        """
+        Generate the init C code for a @block
+        @block: an asm_bloc instance
+        """
+
+        instr_offsets = [line.offset for line in block.lines]
+        instr_offsets.append(self.get_block_post_label(block).offset)
+        lbl_start = self.ir_arch.symbol_pool.getby_offset_create(instr_offsets[0])
+        return (self.CODE_INIT % lbl_start.name).split("\n"), instr_offsets
+
+    def gen_irblock(self, attrib, instr_offsets, instr, irblock):
+        """
+        Generate the C code for an @irblock
+        @instr: the current instruction to translate
+        @irblock: an irbloc instance
+        @attrib: an Attributs instance
+        """
+
+        out = []
+        dst2index = None
+        for index, assignblk in enumerate(irblock.irs):
+            if index == irblock.dst_linenb:
+                c_dst, dst2index = self.gen_assignblk_dst(irblock.dst)
+            else:
+                c_dst = []
+            assignblk.instr_addr = instr.offset
+            prefetchers = self.gen_c_assignblk(assignblk)
+            self.gen_mem_prefetch(assignblk, prefetchers)
+            self.gen_assignments(assignblk, prefetchers)
+
+            out += self.gen_c_code(assignblk, c_dst)
+
+        if dst2index:
+            out.append("// Set irdst")
+            # Gen goto on irdst set
+            out += self.gen_dst_goto(attrib, instr_offsets, dst2index)
+
+        return out
+
+    def gen_finalize(self, block):
+        """
+        Generate the C code for the final block instruction
+        """
+
+        lbl = self.get_block_post_label(block)
+        dst = self.dst_to_c(lbl.offset)
+        code = self.CODE_RETURN_NO_EXCEPTION % (lbl.name, self.C_PC, dst, dst)
+        return code.split('\n')
+
+    def gen_c(self, block, log_mn=False, log_regs=False):
+        """
+        Generate the C code for the @block and return it as a list of lines
+        @log_mn: log mnemonics
+        @log_regs: log registers
+        """
+
+        if isinstance(block, asm_block_bad):
+            return self.gen_bad_block()
+        irblocks_list = self.block2assignblks(block)
+
+        out, instr_offsets = self.gen_init(block)
+
+        for instr, irblocks in zip(block.lines, irblocks_list):
+            attrib = self.get_attributes(instr, irblocks, log_mn, log_regs)
+
+            for index, irblock in enumerate(irblocks):
+                self.ir_arch.irbloc_fix_regs_for_mode(
+                    irblock, self.ir_arch.attrib)
+
+                out.append("%-40s // %.16X %s" %
+                           (str(irblock.label.name) + ":", instr.offset, instr))
+                if index == 0:
+                    out += self.gen_pre_code(attrib)
+                out += self.gen_irblock(attrib, instr_offsets, instr, irblock)
+
+        out += self.gen_finalize(block)
+        return ['\t' + line for line in out]
diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py
index b71e9463..7af2435f 100644
--- a/miasm2/jitter/csts.py
+++ b/miasm2/jitter/csts.py
@@ -13,6 +13,9 @@ EXCEPT_BREAKPOINT_INTERN = (1 << 10)
 EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC)
 EXCEPT_DIV_BY_ZERO = ((1 << 16) | EXCEPT_DO_NOT_UPDATE_PC)
 EXCEPT_PRIV_INSN = ((1 << 17) | EXCEPT_DO_NOT_UPDATE_PC)
+EXCEPT_ILLEGAL_INSN = ((1 << 18) | EXCEPT_DO_NOT_UPDATE_PC)
+EXCEPT_UNK_MNEMO = ((1 << 19) | EXCEPT_DO_NOT_UPDATE_PC)
+
 # VM Mngr constants
 
 PAGE_READ = 1
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
index 74c438a7..6048d62e 100644
--- a/miasm2/jitter/jitcore.py
+++ b/miasm2/jitter/jitcore.py
@@ -95,6 +95,11 @@ class JitCore(object):
         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
+        else:
+            # 1 byte block for unknown mnemonic
+            cur_bloc.ad_min = cur_bloc.label.offset
+            cur_bloc.ad_max = cur_bloc.label.offset+1
+
 
     def add_bloc_to_mem_interval(self, vm, bloc):
         "Update vm to include bloc addresses in its memory range"
@@ -148,10 +153,6 @@ class JitCore(object):
         if self.log_newbloc:
             print cur_bloc
 
-        # Check for empty blocks
-        if not cur_bloc.lines:
-            raise ValueError("Cannot JIT a block without any assembly line")
-
         # Update label -> bloc
         self.lbl2bloc[cur_bloc.label] = cur_bloc
 
diff --git a/miasm2/jitter/jitcore_gcc.py b/miasm2/jitter/jitcore_gcc.py
index a633f935..7f72d8e7 100644
--- a/miasm2/jitter/jitcore_gcc.py
+++ b/miasm2/jitter/jitcore_gcc.py
@@ -9,7 +9,6 @@ from distutils.sysconfig import get_python_inc
 from subprocess import check_call
 from hashlib import md5
 
-from miasm2.ir.ir2C import irblocs2C
 from miasm2.jitter import jitcore, Jitgcc
 from miasm2.core.utils import keydefaultdict
 
@@ -97,6 +96,13 @@ class JitCore_Gcc(jitcore.JitCore):
         self.include_files = include_files
         self.libs = libs
 
+    def init_codegen(self, codegen):
+        """
+        Get the code generator @codegen
+        @codegen: an CGen instance
+        """
+        self.codegen = codegen
+
     def label2fname(self, label):
         """
         Generate function name from @label
@@ -112,7 +118,8 @@ class JitCore_Gcc(jitcore.JitCore):
         self.lbl2jitbloc[label.offset] = addr
         self.gcc_states[label.offset] = lib
 
-    def gen_c_code(self, label, irblocks):
+
+    def gen_c_code(self, label, block):
         """
         Return the C code corresponding to the @irblocks
         @label: asm_label of the block to jit
@@ -120,10 +127,7 @@ class JitCore_Gcc(jitcore.JitCore):
         """
         f_name = self.label2fname(label)
         f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name
-        out = irblocs2C(self.ir_arch, self.resolver, label, irblocks,
-                        gen_exception_code=True,
-                        log_mn=self.log_mn,
-                        log_regs=self.log_regs)
+        out = self.codegen.gen_c(block, log_mn=self.log_mn, log_regs=self.log_regs)
         out = [f_declaration + '{'] + out + ['}\n']
         c_code = out
 
@@ -141,8 +145,7 @@ class JitCore_Gcc(jitcore.JitCore):
         fname_out = os.path.join(self.tempdir, "%s.so" % block_hash)
 
         if not os.access(fname_out, os.R_OK | os.X_OK):
-            irblocks = self.ir_arch.add_bloc(block, gen_pc_updt=True)
-            func_code = self.gen_c_code(block.label, irblocks)
+            func_code = self.gen_c_code(block.label, block)
 
             # Create unique C file
             fdesc, fname_in = tempfile.mkstemp(suffix=".c")
diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py
index 151fab7d..d3e90f85 100644
--- a/miasm2/jitter/jitcore_tcc.py
+++ b/miasm2/jitter/jitcore_tcc.py
@@ -7,7 +7,6 @@ from subprocess import Popen, PIPE
 from hashlib import md5
 import tempfile
 
-from miasm2.ir.ir2C import irblocs2C
 from miasm2.jitter import jitcore, Jittcc
 
 
@@ -141,6 +140,13 @@ class JitCore_Tcc(jitcore.JitCore):
         include_files = ";".join(include_files)
         Jittcc.tcc_set_emul_lib_path(include_files, libs)
 
+    def init_codegen(self, codegen):
+        """
+        Get the code generator @codegen
+        @codegen: an CGen instance
+        """
+        self.codegen = codegen
+
     def __del__(self):
         for tcc_state in self.tcc_states.values():
             Jittcc.tcc_end(tcc_state)
@@ -164,7 +170,7 @@ class JitCore_Tcc(jitcore.JitCore):
         self.lbl2jitbloc[label.offset] = mcode
         self.tcc_states[label.offset] = tcc_state
 
-    def gen_c_code(self, label, irblocks):
+    def gen_c_code(self, label, block):
         """
         Return the C code corresponding to the @irblocks
         @label: asm_label of the block to jit
@@ -172,10 +178,7 @@ class JitCore_Tcc(jitcore.JitCore):
         """
         f_name = self.label2fname(label)
         f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name
-        out = irblocs2C(self.ir_arch, self.resolver, label, irblocks,
-                        gen_exception_code=True,
-                        log_mn=self.log_mn,
-                        log_regs=self.log_regs)
+        out = self.codegen.gen_c(block, log_mn=self.log_mn, log_regs=self.log_regs)
         out = [f_declaration + '{'] + out + ['}\n']
         c_code = out
 
@@ -194,9 +197,7 @@ class JitCore_Tcc(jitcore.JitCore):
         if os.access(fname_out, os.R_OK):
             func_code = open(fname_out).read()
         else:
-            irblocks = self.ir_arch.add_bloc(block, gen_pc_updt=True)
-            block.irblocs = irblocks
-            func_code = self.gen_c_code(block.label, irblocks)
+            func_code = self.gen_c_code(block.label, block)
 
             # Create unique C file
             fdesc, fname_tmp = tempfile.mkstemp(suffix=".c")
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index 2371067d..8943e2c7 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -7,9 +7,9 @@ from collections import Sequence, namedtuple, Iterator
 from miasm2.jitter.csts import *
 from miasm2.core.utils import *
 from miasm2.core.bin_stream import bin_stream_vm
-from miasm2.ir.ir2C import init_arch_C
 from miasm2.core.interval import interval
 from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec
+from miasm2.jitter.codegen import CGen
 
 hnd = logging.StreamHandler()
 hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
@@ -161,11 +161,14 @@ class jitter:
 
     "Main class for JIT handling"
 
+    C_Gen = CGen
+
     def __init__(self, ir_arch, jit_type="tcc"):
         """Init an instance of jitter.
         @ir_arch: ir instance for this architecture
         @jit_type: JiT backend to use. Available options are:
             - "tcc"
+            - "gcc"
             - "llvm"
             - "python"
         """
@@ -194,7 +197,6 @@ class jitter:
         self.cpu = jcore.JitCpu()
         self.ir_arch = ir_arch
         self.bs = bin_stream_vm(self.vm)
-        init_arch_C(self.arch)
 
         self.symbexec = EmulatedSymbExec(self.cpu, self.ir_arch, {})
         self.symbexec.reset_regs()
@@ -214,6 +216,8 @@ class jitter:
             raise RuntimeError('Unsupported jitter: %s' % jit_type)
 
         self.jit = JitCore(self.ir_arch, self.bs)
+        if jit_type in ['tcc', 'gcc']:
+            self.jit.init_codegen(self.C_Gen(self.ir_arch))
 
         self.cpu.init_regs()
         self.vm.init_memory_page_pool()
diff --git a/test/test_all.py b/test/test_all.py
index 35f081de..a487900f 100644
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -232,8 +232,7 @@ for script in ["modint.py",
                ]:
     testset += RegressionTest([script], base_dir="expression")
 ## IR
-for script in ["ir2C.py",
-               "symbexec.py",
+for script in ["symbexec.py",
                ]:
     testset += RegressionTest([script], base_dir="ir")
 testset += RegressionTest(["analysis.py"], base_dir="ir",