about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAymeric Vincent <aymeric.vincent@cea.fr>2018-02-22 16:02:57 +0100
committerAymeric Vincent <aymeric.vincent@cea.fr>2018-02-26 11:34:41 +0100
commitcc2ee2c61dd4719bd7f9a85193590dffcda46991 (patch)
tree8d6b3e6077c97f368dab884b8a889bba75e74f5a
parent0606dd974a5ff0c3d6fb58e002b9319235a2dfbd (diff)
downloadmiasm-cc2ee2c61dd4719bd7f9a85193590dffcda46991.tar.gz
miasm-cc2ee2c61dd4719bd7f9a85193590dffcda46991.zip
Add support for PowerPC 32bit big-endian processors: "ppc32b"
-rw-r--r--example/jitter/sandbox_elf_ppc32.py25
-rw-r--r--miasm2/analysis/machine.py13
-rw-r--r--miasm2/analysis/sandbox.py85
-rw-r--r--miasm2/arch/ppc/__init__.py1
-rw-r--r--miasm2/arch/ppc/arch.py759
-rw-r--r--miasm2/arch/ppc/disasm.py7
-rw-r--r--miasm2/arch/ppc/ira.py47
-rw-r--r--miasm2/arch/ppc/jit.py70
-rw-r--r--miasm2/arch/ppc/regs.py59
-rw-r--r--miasm2/arch/ppc/sem.py921
-rw-r--r--miasm2/jitter/Makefile7
-rw-r--r--miasm2/jitter/arch/JitCore_ppc32.c373
-rw-r--r--miasm2/jitter/arch/JitCore_ppc32.h24
-rw-r--r--miasm2/jitter/arch/JitCore_ppc32_regs.h89
-rw-r--r--miasm2/jitter/csts.py1
-rw-r--r--miasm2/jitter/jitload.py4
-rwxr-xr-xsetup.py13
17 files changed, 2494 insertions, 4 deletions
diff --git a/example/jitter/sandbox_elf_ppc32.py b/example/jitter/sandbox_elf_ppc32.py
new file mode 100644
index 00000000..c5960e8e
--- /dev/null
+++ b/example/jitter/sandbox_elf_ppc32.py
@@ -0,0 +1,25 @@
+import os
+from pdb import pm
+from miasm2.analysis.sandbox import Sandbox_Linux_ppc32b
+from miasm2.jitter.csts import *
+from miasm2.jitter.jitload import log_func
+import logging
+
+
+# Python auto completion
+filename = os.environ.get('PYTHONSTARTUP')
+if filename and os.path.isfile(filename):
+    execfile(filename)
+
+# Insert here user defined methods
+
+# Parse arguments
+parser = Sandbox_Linux_ppc32b.parser(description="ELF sandboxer")
+parser.add_argument("filename", help="ELF Filename")
+options = parser.parse_args()
+
+# Create sandbox
+sb = Sandbox_Linux_ppc32b(options.filename, options, globals())
+log_func.setLevel(logging.ERROR)
+
+sb.run()
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py
index 7a6069c0..f361b412 100644
--- a/miasm2/analysis/machine.py
+++ b/miasm2/analysis/machine.py
@@ -12,7 +12,7 @@ class Machine(object):
 
     __available = ["arml", "armb", "armtl", "armtb", "sh4", "x86_16", "x86_32",
                    "x86_64", "msp430", "mips32b", "mips32l",
-                   "aarch64l", "aarch64b"]
+                   "aarch64l", "aarch64b", "ppc32b"]
 
 
     def __init__(self, machine_name):
@@ -162,6 +162,17 @@ class Machine(object):
             mn = arch.mn_mips32
             from miasm2.arch.mips32.ira import ir_a_mips32l as ira
             from miasm2.arch.mips32.sem import ir_mips32l as ir
+        elif machine_name == "ppc32b":
+            from miasm2.arch.ppc.disasm import dis_ppc32b as dis_engine
+            from miasm2.arch.ppc import arch
+            try:
+                from miasm2.arch.ppc import jit
+                jitter = jit.jitter_ppc32b
+            except ImportError:
+                pass
+            mn = arch.mn_ppc
+            from miasm2.arch.ppc.ira import ir_a_ppc32b as ira
+            from miasm2.arch.ppc.sem import ir_ppc32b as ir
         else:
             raise ValueError('Unknown machine: %s' % machine_name)
 
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index 086473b0..5bdccddd 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -440,6 +440,14 @@ class Arch_aarch64b(Arch):
         self.jitter.stack_base = self.STACK_BASE
         self.jitter.init_stack()
 
+class Arch_ppc(Arch):
+    _ARCH_ = None
+
+class Arch_ppc32(Arch):
+    _ARCH_ = None
+
+class Arch_ppc32b(Arch_ppc32):
+    _ARCH_ = "ppc32b"
 
 class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win):
 
@@ -745,3 +753,80 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux):
         """
         prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv)
         super(self.__class__, self).call(prepare_cb, addr, *args)
+
+class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux):
+
+    STACK_SIZE = 0x10000
+    STACK_BASE = 0xbfce0000
+
+    # The glue between the kernel and the ELF ABI on Linux/PowerPC is
+    # implemented in glibc/sysdeps/powerpc/powerpc32/dl-start.S, so we
+    # have to play the role of ld.so here.
+    def __init__(self, *args, **kwargs):
+        super(Sandbox_Linux_ppc32b, self).__init__(*args, **kwargs)
+
+        # Init stack
+        self.jitter.stack_size = self.STACK_SIZE
+        self.jitter.stack_base = self.STACK_BASE
+        self.jitter.init_stack()
+        self.jitter.cpu.R1 -= 8
+
+        # Pre-stack some arguments
+        if self.options.mimic_env:
+            env_ptrs = []
+            for env in self.envp:
+                env += "\x00"
+                self.jitter.cpu.R1 -= len(env)
+                ptr = self.jitter.cpu.R1
+                self.jitter.vm.set_mem(ptr, env)
+                env_ptrs.append(ptr)
+            argv_ptrs = []
+            for arg in self.argv:
+                arg += "\x00"
+                self.jitter.cpu.R1 -= len(arg)
+                ptr = self.jitter.cpu.R1
+                self.jitter.vm.set_mem(ptr, arg)
+                argv_ptrs.append(ptr)
+
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(env_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.cpu.R5 = self.jitter.cpu.R1	# envp
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(argv_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.cpu.R4 = self.jitter.cpu.R1	# argv
+            self.jitter.cpu.R3 = len(self.argv)		# argc
+            self.jitter.push_uint32_t(self.jitter.cpu.R3)
+
+            self.jitter.cpu.R6 = 0			# auxp
+            self.jitter.cpu.R7 = 0			# termination function
+
+            # From the glibc, we should push a 0 here to distinguish a
+            # dynamically linked executable from a statically linked one.
+            # We actually do not do it and attempt to be somehow compatible
+            # with both types of executables.
+            #self.jitter.push_uint32_t(0)
+
+        self.jitter.cpu.LR = self.CALL_FINISH_ADDR
+
+        # Set the runtime guard
+        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR,
+                                   self.__class__.code_sentinelle)
+
+    def run(self, addr=None):
+        """
+        If addr is not set, use entrypoint
+        """
+        if addr is None and self.options.address is None:
+            addr = self.entry_point
+        super(Sandbox_Linux_ppc32b, self).run(addr)
+
+    def call(self, addr, *args, **kwargs):
+        """
+        Direct call of the function at @addr, with arguments @args
+        @addr: address of the target function
+        @args: arguments
+        """
+        prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv)
+        super(self.__class__, self).call(prepare_cb, addr, *args)
diff --git a/miasm2/arch/ppc/__init__.py b/miasm2/arch/ppc/__init__.py
new file mode 100644
index 00000000..bbad893b
--- /dev/null
+++ b/miasm2/arch/ppc/__init__.py
@@ -0,0 +1 @@
+__all__ = ["arch", "disasm", "regs", "sem"]
diff --git a/miasm2/arch/ppc/arch.py b/miasm2/arch/ppc/arch.py
new file mode 100644
index 00000000..d47c2aad
--- /dev/null
+++ b/miasm2/arch/ppc/arch.py
@@ -0,0 +1,759 @@
+
+import logging
+from pyparsing import *
+from miasm2.expression.expression import *
+from miasm2.core.cpu import *
+from collections import defaultdict
+from miasm2.core.bin_stream import bin_stream
+from miasm2.core.asmblock import asm_label
+import miasm2.arch.ppc.regs as regs_module
+from miasm2.arch.ppc.regs import *
+from pdb import pm
+
+log = logging.getLogger("ppcdis")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.DEBUG)
+
+LPARENTHESIS = Suppress(Literal("("))
+RPARENTHESIS = Suppress(Literal(")"))
+
+def deref2expr_imm_reg(s, l, t):
+    t = t[0]
+    if len(t) == 1:
+        return ExprMem(t[0])
+    elif len(t) == 2:
+        return ExprMem(t[1] + t[0])
+    else:
+        raise NotImplementedError('len(t) > 2')
+
+variable, operand, base_expr = gen_base_expr()
+
+int_or_expr = base_expr
+
+
+def ast_id2expr(t):
+    if not t in mn_ppc.regs.all_regs_ids_byname:
+        r = ExprId(asm_label(t))
+    else:
+        r = mn_ppc.regs.all_regs_ids_byname[t]
+    return r
+
+def ast_int2expr(a):
+    return ExprInt(a, 32)
+
+deref_reg_disp = Group(Optional(int_or_expr) + LPARENTHESIS + gpregs.parser +  RPARENTHESIS).setParseAction(deref2expr_imm_reg)
+deref_reg = Group(LPARENTHESIS + gpregs.parser +  RPARENTHESIS).setParseAction(deref2expr_imm_reg)
+
+deref = deref_reg | deref_reg_disp
+
+my_var_parser = ParseAst(ast_id2expr, ast_int2expr)
+base_expr.setParseAction(my_var_parser)
+
+
+class additional_info:
+
+    def __init__(self):
+        self.except_on_instr = False
+        self.bo_bi_are_defined = False
+        self.bi = 0
+        self.bo = 0
+
+
+class instruction_ppc(instruction):
+    delayslot = 0
+
+    def __init__(self, *args, **kargs):
+        super(instruction_ppc, self).__init__(*args, **kargs)
+
+    @staticmethod
+    def arg2str(e, pos = None):
+        if isinstance(e, ExprId) or isinstance(e, ExprInt):
+            return str(e)
+        elif isinstance(e, ExprMem):
+            addr = e.arg
+            if isinstance(addr, ExprInt) or isinstance(addr, ExprId):
+                out = '(%s)'%addr
+            elif isinstance(addr, ExprOp):
+                if len(addr.args) == 1:
+                    out = '(%s)'%addr
+                elif len(addr.args) == 2:
+                    out = '%s(%s)'%(addr.args[1], addr.args[0])
+                else:
+                    raise NotImplementedError('More than two args to ExprOp of address')
+            else:
+                raise NotImplementedError('Invalid memory expression')
+            return out
+
+        return str(e)
+
+    @staticmethod
+    def is_conditional_jump(s):
+        return (s[0] == 'B' and
+                s[1:3] in { 'DN', 'DZ', 'LT', 'GT', 'EQ', 'SO',
+                            'GE', 'LE', 'NE', 'NS' })
+
+    def dstflow(self):
+        name = self.name
+        if name[-1] == '+' or name[-1] == '-':
+            name = name[:-1]
+        return (name[0] == 'B' and
+                name[-2:] != 'LR' and
+                name[-3:] != 'LRL' and
+                name[-3:] != 'CTR' and
+                name[-4:] != 'CTRL')
+
+    def dstflow2label(self, symbol_pool):
+        name = self.name
+        if name[-1] == '+' or name[-1] == '-':
+            name = name[:-1]
+
+        if name[-1] == 'L':
+            name = name[:-1]
+        elif name[-2:] == 'LA':
+            name = name[:-2] + 'A'
+
+        if name[-2:] != 'LR' and name[-3:] != 'CTR':
+            if self.is_conditional_jump(name):
+                address_index = 1
+            else:
+                address_index = 0
+            e = self.args[address_index]
+            if not isinstance(e, ExprInt):
+                return
+            if name[-1] != 'A':
+                ad = e.arg + self.offset
+            else:
+                ad = e.arg
+            l = symbol_pool.getby_offset_create(ad)
+            s = ExprId(l, e.size)
+            self.args[address_index] = s
+
+    def breakflow(self):
+        return self.name[0] == 'B'
+
+    def is_subcall(self):
+        name = self.name
+        if name[-1] == '+' or name[-1] == '-':
+            name = name[0:-1]
+        return name[0] == 'B' and (name[-1] == 'L' or name[-2:-1] == 'LA')
+
+    def getdstflow(self, symbol_pool):
+        if 'LR' in self.name:
+            return [ LR ]
+        elif 'CTR' in self.name:
+            return [ CTR ]
+        elif self.is_conditional_jump(self.name):
+            address_index = 1
+        else:
+            address_index = 0
+        return [ self.args[address_index] ]
+
+    def splitflow(self):
+        ret = False
+        if self.is_conditional_jump(self.name):
+            if self.additional_info.bo & 0b10100 != 0b10100:
+                ret = True
+        ret = ret or self.is_subcall()
+        return ret
+
+    def get_symbol_size(self, symbol, symbol_pool):
+        return 32
+
+    def fixDstOffset(self):
+        e = self.args[0]
+        if not isinstance(e, ExprInt):
+            log.debug('Dynamic destination offset %r' % e)
+            return
+        if self.name[-1] != 'A':
+            if self.offset is None:
+                raise ValueError('symbol not resolved %s' % self.l)
+            off = e.arg - (self.offset + self.l)
+            if int(off % 4):
+                raise ValueError('Offset %r must be a multiple of four' % off)
+        else:
+            off = e.arg
+        self.args[0] = ExprInt(off, 32)
+
+    def get_args_expr(self):
+        args = [a for a in self.args]
+        return args
+
+    def get_asm_offset(self, x):
+        return ExprInt_from(x, self.offset)
+
+
+class mn_ppc(cls_mn):
+    delayslot = 0
+    name = "ppc32"
+    regs = regs_module
+    bintree = {}
+    num = 0
+    all_mn = []
+    all_mn_mode = defaultdict(list)
+    all_mn_name = defaultdict(list)
+    all_mn_inst = defaultdict(list)
+    instruction = instruction_ppc
+    max_instruction_len = 4
+
+    @classmethod
+    def getpc(cls, attrib = None):
+        return PC
+
+    @classmethod
+    def getsp(cls, attrib = None):
+        return R1
+
+    def additional_info(self):
+        info = additional_info()
+        info.bo_bi_are_defined = False
+        if hasattr(self, "bo"):
+            info.bo_bi_are_defined = True
+            info.bi = int(self.bi.strbits, 2)
+            info.bo = int(self.bo.strbits, 2)
+        return info
+
+    @classmethod
+    def getbits(cls, bs, attrib, start, n):
+        if not n:
+            return 0
+        o = 0
+        if n > bs.getlen() * 8:
+            raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8))
+        while n:
+            offset = start / 8
+            n_offset = cls.endian_offset(attrib, offset)
+            c = cls.getbytes(bs, n_offset, 1)
+            if not c:
+                raise IOError
+            c = ord(c)
+            r = 8 - start % 8
+            c &= (1 << r) - 1
+            l = min(r, n)
+            c >>= (r - l)
+            o <<= l
+            o |= c
+            n -= l
+            start += l
+        return o
+
+    @classmethod
+    def endian_offset(cls, attrib, offset):
+        if attrib == "b":
+            return offset
+        else:
+            raise NotImplementedError("bad attrib")
+
+    @classmethod
+    def check_mnemo(cls, fields):
+        l = sum([x.l for x in fields])
+        assert l == 32, "len %r" % l
+
+    @classmethod
+    def getmn(cls, name):
+        return name.upper()
+
+    @classmethod
+    def mod_fields(cls, fields):
+        l = sum([x.l for x in fields])
+        return fields
+
+    @classmethod
+    def gen_modes(cls, subcls, name, bases, dct, fields):
+        dct['mode'] = None
+        return [(subcls, name, bases, dct, fields)]
+
+    def post_dis(self):
+        return self
+
+    def value(self, mode):
+        v = super(mn_ppc, self).value(mode)
+        if mode == 'b':
+            return [x for x in v]
+        else:
+            raise NotImplementedError("bad attrib")
+
+    def get_symbol_size(self, symbol, symbol_pool, mode):
+        return 32
+
+
+class ppc_reg(reg_noarg, m_arg):
+    pass
+
+
+class ppc_gpreg_noarg(reg_noarg):
+    reg_info = gpregs
+    parser = reg_info.parser
+
+class ppc_gpreg_or_0_noarg(reg_noarg):
+    reg_info = gpregs
+    parser = reg_info.parser
+
+    def decode(self, v):
+        ret = super(ppc_gpreg_or_0_noarg, self).decode(v)
+        if ret == False:
+            return False
+        reg = self.expr
+        if reg == R0:
+            self.expr = ExprInt(0, 32)
+        return ret
+
+class ppc_gpreg(ppc_reg):
+    reg_info = gpregs
+    parser = reg_info.parser
+
+class ppc_gpreg_or_0(ppc_reg):
+    reg_info = gpregs
+    parser = reg_info.parser
+
+    def decode(self, v):
+        ret = super(ppc_reg, self).decode(v)
+        if ret == False:
+            return False
+        reg = self.expr
+        if reg == R0:
+            self.expr = ExprInt(0, 32)
+        return ret
+
+class ppc_crfreg_noarg(reg_noarg):
+    reg_info = crfregs
+    parser = reg_info.parser
+
+class ppc_crfreg(ppc_reg):
+    reg_info = crfregs
+    parser = reg_info.parser
+
+class ppc_imm(imm_noarg, m_arg):
+    parser = base_expr
+
+class ppc_s14imm_branch(ppc_imm):
+
+    def decode(self, v):
+        v = sign_ext(v << 2, 16, 32)
+        self.expr = ExprInt(v, 32)
+        return True
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = self.expr.arg.arg
+        if v & 0x3:
+            return False
+        v = v >> 2
+        if sign_ext(v & self.lmask, 14, 32) != v:
+            return False
+        self.value = v & self.lmask
+        return True
+
+class ppc_s24imm_branch(ppc_imm):
+
+    def decode(self, v):
+        v = sign_ext(v << 2, 26, 32)
+        self.expr = ExprInt(v, 32)
+        return True
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = self.expr.arg.arg
+        if v & 0x3:
+            return False
+        v = v >> 2
+        if sign_ext(v & self.lmask, 24, 32) != v:
+            return False
+        self.value = v & self.lmask
+        return True
+
+class ppc_s16imm(ppc_imm):
+
+    def decode(self, v):
+        v = sign_ext(v, 16, 32)
+        self.expr = ExprInt(v, 32)
+        return True
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = self.expr.arg.arg
+        if sign_ext(v & self.lmask, 16, 32) != v:
+            return False
+        self.value = v & self.lmask
+        return True
+
+class ppc_u16imm(ppc_imm):
+
+    def decode(self, v):
+        if v & self.lmask != v:
+            return False
+        self.expr = ExprInt(v, 32)
+        return True
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = self.expr.arg.arg
+        if v & self.lmask != v:
+            return False
+        self.value = v & self.lmask
+        return True
+
+def ppc_swap_10(v):
+    return ((v & 0b11111) << 5) | ((v & 0b1111100000) >> 5)
+
+class ppc_spr(ppc_imm):
+
+    def decode(self, v):
+        self.expr = ExprInt(ppc_swap_10(v), 32)
+        return True
+
+    def encode(self, e):
+        if not isinstance(e, ExprInt):
+            return False
+        self.value = ppc_swap_10(e.arg)
+        return True
+
+class ppc_tbr(ppc_imm):
+
+    def decode(self, v):
+        self.expr = ExprInt(ppc_swap_10(v), 32)
+        return True
+
+    def encode(self, e):
+        if not isinstance(e, ExprInt):
+            return False
+        self.value = ppc_swap_10(e.arg)
+        return True
+
+class ppc_u08imm(ppc_u16imm):
+    pass
+
+class ppc_u05imm(ppc_u16imm):
+    pass
+
+class ppc_u04imm(ppc_u16imm):
+    pass
+
+class ppc_u02imm_noarg(imm_noarg):
+    pass
+
+
+def ppc_bo_bi_to_mnemo(bo, bi, prefer_taken=True, default_taken=True):
+    bo2mnemo = { 0: 'DNZF', 2: 'DZF', 4: 'F', 8: 'DNZT',
+                 10: 'DZT', 12: 'T', 16: 'DNZ', 18: 'DZ',
+                 20: '' }
+    bi2cond = { 0b00: 'LT', 0b01: 'GT', 0b10: 'EQ', 0b11: 'SO' }
+    bi2ncond = { 0b00: 'GE', 0b01: 'LE', 0b10: 'NE', 0b11: 'NS' }
+    n = bo & 0b11110
+    if not n in bo2mnemo:
+        raise NotImplementedError("Unknown BO field")
+    mnem = 'B' + bo2mnemo[n]
+    if mnem[-1] == 'T':
+        mnem = mnem[:-1] + bi2cond[bi & 0b11]
+    if mnem[-1] == 'F':
+        mnem = mnem[:-1] + bi2ncond[bi & 0b11]
+
+    if prefer_taken != default_taken:
+        if prefer_taken:
+            mnem += '+'
+        else:
+            mnem += '-'
+
+    return mnem
+
+def ppc_all_bo_bi():
+    yield 20, 0
+
+    for bo in [0, 2, 4, 8, 10, 12, 16, 18]:
+        for bi in xrange(4):
+            yield bo, bi
+
+class ppc_divert_conditional_branch(bs_divert):
+    prio=3
+    def divert(self, i, candidates):
+        out = []
+        for cls, _, bases, dct, fields in candidates:
+            bi_i = getfieldindexby_name(fields, 'bi')[1]
+            bo_i = getfieldindexby_name(fields, 'bo')[1]
+
+            for bo, bi in ppc_all_bo_bi():
+                nfields = fields[:]
+                nfields[bi_i] = bs(int2bin(bi, 2), fname="bi")
+                nfields[bo_i] = bs(int2bin(bo, 5), fname="bo")
+                ndct = dict(dct)
+                ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi)
+                out.append((cls, ndct['name'], bases, ndct, nfields))
+
+                nfields = fields[:]
+                nfields[bi_i] = bs(int2bin(bi, 2), fname="bi")
+                nfields[bo_i] = bs(int2bin(bo+1, 5), fname="bo")
+                ndct = dict(dct)
+                ndct['name'] = ppc_bo_bi_to_mnemo(bo, bi)
+                out.append((cls, ndct['name'], bases, ndct, nfields))
+
+        return out
+
+class ppc_deref32(m_arg):
+    parser = deref
+
+    def decode(self, v):
+        v = sign_ext(v, 16, 32)
+        e = self.parent.ra.expr + ExprInt(v, 32)
+        self.expr = ExprMem(e, size=32)
+        return True
+
+    def encode(self):
+        e = self.expr
+        if not isinstance(e, ExprMem):
+            return False
+        addr = e.arg
+        if isinstance(addr, ExprId) or isinstance(addr, ExprInt):
+            addr = addr + ExprInt(0, 32)
+        elif not isinstance(addr, ExprOp):
+            return False
+        if addr.op != '+':
+            return False
+        if len(addr.args) != 2:
+            return False
+        reg, disp = addr.args[0], addr.args[1]
+        v = int(disp.arg)
+        if sign_ext(v & 0xFFFF, 16, 32) != v:
+            return False
+        v &= 0xFFFF
+        self.value = v
+        self.parent.ra.expr = reg
+        return True
+
+
+def ppcop(name, fields, args=None, alias=False):
+    dct = {"fields": fields}
+    dct["alias"] = alias
+    if args is not None:
+        dct['args'] = args
+    type(name, (mn_ppc,), dct)
+
+rd = bs(l=5, cls=(ppc_gpreg,))
+ra = bs(l=5, cls=(ppc_gpreg,))
+ra_or_0 = bs(l=5, cls=(ppc_gpreg_or_0,))
+rb = bs(l=5, cls=(ppc_gpreg,))
+rs = bs(l=5, cls=(ppc_gpreg,))
+crfd = bs(l=3, cls=(ppc_crfreg,))
+crfs = bs(l=3, cls=(ppc_crfreg,))
+sh = bs(l=5, cls=(ppc_u05imm,))
+mb = bs(l=5, cls=(ppc_u05imm,))
+me = bs(l=5, cls=(ppc_u05imm,))
+nb = bs(l=5, cls=(ppc_u05imm,))
+crm = bs(l=8, cls=(ppc_u08imm,))
+sr = bs(l=4, cls=(ppc_u04imm,))
+spr = bs(l=10, cls=(ppc_spr,))
+tbr = bs(l=10, cls=(ppc_tbr,))
+u05imm = bs(l=5, cls=(ppc_u05imm,))
+
+s24imm_branch = bs(l=24, cls=(ppc_s24imm_branch,), fname="imm")
+s14imm_branch = bs(l=14, cls=(ppc_s14imm_branch,), fname="imm")
+s16imm = bs(l=16, cls=(ppc_s16imm,), fname="imm")
+u16imm = bs(l=16, cls=(ppc_u16imm,), fname="imm")
+u08imm = bs(l=5, cls=(ppc_u08imm,), fname="imm")
+u02imm_noarg = bs(l=2, cls=(ppc_u02imm_noarg,), fname="imm")
+
+ra_noarg = bs(l=5, cls=(ppc_gpreg_noarg,), fname="ra")
+ra_or_0_noarg = bs(l=5, cls=(ppc_gpreg_or_0_noarg,), fname="ra")
+dregimm = bs(l=16, cls=(ppc_deref32,))
+
+rc_mod = bs_mod_name(l=1, mn_mod=['', '.'], fname='rc')
+
+arith1_name = {"MULLI": 0b000111, "SUBFIC": 0b001000, "ADDIC": 0b001100,
+               "ADDIC.": 0b001101 }
+
+logic2_name = {"ORI": 0b011000, "XORI": 0b011010, "ANDI.": 0b011100 }
+slogic2_name = {"ORIS": 0b011001, "XORIS": 0b011011, "ANDIS.": 0b011101 }
+
+arith3_name = {"SUBFC": 0b0000001000, "ADDC": 0b0000001010,
+               "MULHWU": 0b0000001011, "SUBF": 0b0000101000,
+               "MULHW": 0b0001001011, "SUBFE": 0b0010001000,
+               "ADDE": 0b0010001010, "MULLW": 0b0011101011,
+               "ADD": 0b0100001010, "DIVWU": 0b0111001011,
+               "DIVW": 0b0111101011, "SUBFCO": 0b1000001000,
+               "ADDCO": 0b1000001010, "SUBFO": 0b1000101000,
+               "SUBFEO": 0b1010001000, "ADDEO": 0b1010001010,
+               "MULLWO": 0b1011101011, "ADDO": 0b1100001010,
+               "DIVWUO": 0b1111001011, "DIVWO": 0b1111101011 }
+
+xor_name = { "EQV": 0b0100011100, "XOR": 0b0100111100 }
+
+arith4_name = {"NEG": 0b0001101000, "SUBFZE": 0b0011001000,
+               "ADDZE": 0b0011001010, "SUBFME": 0b0011101000,
+               "ADDME": 0b0011101010, "NEGO": 0b1001101000,
+               "SUBFZEO": 0b1011001000, "ADDZEO": 0b1011001010,
+               "SUBFMEO": 0b1011101000, "ADDMEO": 0b1011101010 }
+
+arith5_name = {"CNTLZW": 0b00000, "EXTSH": 0b11100, "EXTSB": 0b11101 }
+
+crlogic_name = {"CRAND": 0b1000, "CRANDC": 0b0100, "CREQV": 0b1001,
+                "CRNAND": 0b0111, "CRNOR": 0b0001, "CROR": 0b1110,
+                "CRORC": 0b1101, "CRXOR": 0b0110 }
+
+rotins_name = {"RLWIMI": 0b010100, "RLWINM": 0b010101 }
+
+bs_arith1_name = bs_name(l=6, name=arith1_name)
+
+load1_name = {"LWARX": 0b0000010100, "LWZX": 0b0000010111,
+              "LBZX": 0b0001010111, "LHZX": 0b0100010111,
+              "ECIWX": 0b0100110110, "LHAX": 0b0101010111,
+              "LSWX": 0b1000010101, "LWBRX": 0b1000010110,
+              "LHBRX": 0b1100010110 }
+
+load1_name_u = {"LWZUX": 0b0000110111, "LBZUX": 0b0001110111,
+                "LHZUX": 0b0100110111, "LHAUX": 0b0101110111 }
+
+load2_name = {"LWZ": 0b0000, "LBZ": 0b0010, "LHZ": 0b1000, "LHA": 0b1010,
+              "LMW": 0b1110 }
+
+load2_name_u = {"LWZU": 0b0001, "LBZU": 0b0011, "LHZU": 0b1001, "LHAU": 0b1011}
+
+store1_name = { "STWCX.": 0b00100101101, "STWX": 0b00100101110,
+                "STBX": 0b00110101110, "STHX": 0b01100101110,
+                "ECOWX": 0b01101101100, "STSWX": 0b10100101010,
+                "STWBRX": 0b10100101100, "STHBRX": 0b11100101100 }
+store1_name_u = { "STWUX": 0b00101101110, "STBUX": 0b00111101110,
+                  "STHUX": 0b01101101110 }
+
+store2_name = { "STW": 0b0100, "STB": 0b0110, "STH": 0b1100, "STMW": 0b1111 }
+store2_name_u = { "STWU": 0b0101, "STBU": 0b0111, "STHU": 0b1101 }
+
+logic1_name = {"SLW": 0b0000011000, "AND": 0b0000011100,
+               "ANDC": 0b0000111100, "NOR": 0b0001111100,
+               "ORC": 0b0110011100, "OR": 0b0110111100,
+               "NAND": 0b0111011100, "SRW": 0b1000011000,
+               "SRAW": 0b1100011000 }
+
+dcb_name = {"DCBST": 0b00001, "DCBF": 0b00010,
+            "DCBTST": 0b00111, "DCBT": 0b01000,
+            "DCBI": 0b01110, "DCBA": 0b10111,
+            "ICBI": 0b11110, "DCBZ": 0b11111 }
+
+class bs_mod_name_prio4(bs_mod_name):
+    prio = 4
+
+class bs_mod_name_prio5(bs_mod_name):
+    prio = 5
+
+class bs_mod_name_prio6(bs_mod_name):
+    prio = 6
+
+branch_to_reg = bs_mod_name_prio4(l=1, mn_mod=['LR', 'CTR'], fname='btoreg')
+branch_lk = bs_mod_name_prio5(l=1, mn_mod=['', 'L'], fname='lk')
+branch_aa = bs_mod_name_prio6(l=1, mn_mod=['', 'A'], fname='aa')
+
+ppcop("arith1", [bs_arith1_name, rd, ra, s16imm])
+ppcop("ADDIS", [bs('001111'), rd, ra_or_0, u16imm])
+ppcop("ADDI", [bs('001110'), rd, ra_or_0, s16imm])
+
+ppcop("logic2", [bs_name(l=6, name=logic2_name), rs, ra, u16imm],
+      [ra, rs, u16imm])
+ppcop("slogic2", [bs_name(l=6, name=slogic2_name), rs, ra, u16imm],
+      [ra, rs, u16imm])
+
+ppcop("store1", [bs('011111'), rs, ra_or_0, rb,
+                 bs_name(l=11, name=store1_name_u)])
+ppcop("store1u", [bs('011111'), rs, ra, rb, bs_name(l=11, name=store1_name)])
+
+ppcop("store2", [bs('10'), bs_name(l=4, name=store2_name), rs,
+                    ra_noarg, dregimm])
+ppcop("store2u", [bs('10'), bs_name(l=4, name=store2_name_u), rs,
+                    ra_or_0_noarg, dregimm])
+
+ppcop("arith3", [bs('011111'), rd, ra, rb, bs_name(l=10, name=arith3_name),
+                 rc_mod])
+
+ppcop("xor", [bs('011111'), rs, ra, rb, bs_name(l=10, name=xor_name),
+                 rc_mod], [ra, rs, rb])
+
+ppcop("arith4", [bs('011111'), rd, ra, bs('00000'),
+                 bs_name(l=10, name=arith4_name), rc_mod])
+
+ppcop("arith5", [bs('011111'), rs, ra, bs('00000'),
+                 bs_name(l=5, name=arith5_name),
+                 bs('11010'), rc_mod], [ra, rs])
+
+ppcop("load1", [bs('011111'), rd, ra_or_0, rb,
+                bs_name(l=10, name=load1_name), bs('0')])
+ppcop("load1u", [bs('011111'), rd, ra, rb,
+                 bs_name(l=10, name=load1_name_u), bs('0')])
+ppcop("load2", [bs('10'), bs_name(l=4, name=load2_name),
+                rd, ra_or_0_noarg, dregimm])
+ppcop("load2u", [bs('10'), bs_name(l=4, name=load2_name_u),
+                 rd, ra_noarg, dregimm])
+
+ppcop("logic1", [bs('011111'), rs, ra, rb, bs_name(l=10, name=logic1_name),
+                 rc_mod],
+      [ra, rs, rb])
+
+ppcop("TWI", [bs('000011'), u05imm, ra, s16imm])
+ppcop("TW", [bs('011111'), u05imm, ra, rb, bs('00000001000')])
+
+ppcop("CMPW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00000000000')])
+ppcop("CMPLW", [bs('011111'), crfd, bs('00'), ra, rb, bs('00001000000')])
+ppcop("CMPLWI", [bs('001010'), crfd, bs('00'), ra, u16imm])
+ppcop("CMPWI", [bs('001011'), crfd, bs('00'), ra, s16imm])
+
+ppcop("BC", [bs('010000'), bs(l=5, cls=(ppc_u05imm,), fname='bo'),
+             crfs,
+             ppc_divert_conditional_branch(l=2, fname='bi'),
+             s14imm_branch, branch_aa, branch_lk])
+ppcop("SC", [bs('01000100000000000000000000000010')])
+ppcop("B", [bs('010010'), s24imm_branch, branch_aa, branch_lk])
+ppcop("MCRF", [bs('010011'), crfd, bs('00'), crfs, bs('000000000000000000')])
+
+ppcop("BCXXX", [bs('010011'), bs(l=5, cls=(ppc_u05imm,), fname='bo'),
+                crfs,
+                ppc_divert_conditional_branch(l=2, fname='bi'),
+                bs('00000'), branch_to_reg,
+                bs('000010000'), branch_lk])
+
+ppcop("crlogic", [bs('010011'),
+                  bs(l=5, cls=(ppc_u05imm,), fname='crbd'),
+                  bs(l=5, cls=(ppc_u05imm,), fname='crba'),
+                  bs(l=5, cls=(ppc_u05imm,), fname='crbb'),
+                  bs('0'),
+                  bs_name(l=4, name=crlogic_name),
+                  bs('000010')])
+
+ppcop("rotins", [bs_name(l=6, name=rotins_name),
+                 rs, ra, sh, mb, me, rc_mod],
+      [ ra, rs, sh, mb, me ])
+ppcop("RLWNM", [bs('010111'), rs, ra, rb, mb, me, rc_mod],
+      [ ra, rs, rb, mb, me ])
+ppcop("MFXXX", [bs('011111'), rd, bs('0000000000'),
+                bs('000'),
+                bs_name(l=1, name={'MFCR':0, 'MFMSR':1}),
+                bs('0100110')])
+
+ppcop("dcb", [bs('01111100000'), ra, rb, bs_name(l=5, name=dcb_name),
+              bs('101100')])
+
+ppcop("MTCRF", [bs('011111'), rs, bs('0'), crm, bs('000100100000')], [crm, rs])
+ppcop("MTMSR", [bs('011111'), rs, bs('0000000000'), bs('00100100100')])
+ppcop("MTSR", [bs('011111'), rs, bs('0'), sr, bs('0000000110100100')], [sr, rs])
+ppcop("MTSRIN", [bs('011111'), rs, bs('00000'), rb, bs('00111100100')])
+
+ppcop("TLBIE", [bs('011111'), bs('0000000000'), rb, bs('01001100100')])
+ppcop("MFSPR", [bs('011111'), rd, spr, bs('01010100110')])
+ppcop("TLBIA", [bs('01111100000000000000001011100100')])
+ppcop("MFTB", [bs('011111'), rd, tbr, bs('01011100110')])
+ppcop("RFI", [bs('01001100000000000000000001100100')])
+ppcop("ISYNC", [bs('01001100000000000000000100101100')])
+ppcop("MTSPR", [bs('011111'), rs, spr, bs('01110100110')], [spr, rs])
+ppcop("MCRXR", [bs('011111'), crfd, bs('000000000000'),
+                bs('10000000000')])
+ppcop("TLBSYNC", [bs('01111100000000000000010001101100')])
+ppcop("MFSR", [bs('011111'), rd, bs('0'), sr, bs('00000'), bs('10010100110')])
+ppcop("LSWI", [bs('011111'), rd, ra, nb, bs('10010101010')])
+ppcop("STSWI", [bs('011111'), rs, ra, nb, bs('10110101010')])
+ppcop("SYNC", [bs('011111'), bs('000000000000000'), bs('10010101100')])
+ppcop("MFSRIN", [bs('011111'), rd, bs('00000'), rb, bs('10100100110')])
+
+ppcop("SRAWI", [bs('011111'), rs, ra, sh, bs('1100111000'), rc_mod],
+      [ra, rs, sh])
+
+ppcop("EIEIO", [bs('011111'), bs('000000000000000'), bs('11010101100')])
diff --git a/miasm2/arch/ppc/disasm.py b/miasm2/arch/ppc/disasm.py
new file mode 100644
index 00000000..9fe3d886
--- /dev/null
+++ b/miasm2/arch/ppc/disasm.py
@@ -0,0 +1,7 @@
+from miasm2.arch.ppc.arch import mn_ppc
+from miasm2.core.asmblock import disasmEngine
+
+class dis_ppc32b(disasmEngine):
+    def __init__(self, bs=None, **kwargs):
+        super(dis_ppc32b, self).__init__(mn_ppc, None, bs, **kwargs)
+        self.attrib = 'b'
diff --git a/miasm2/arch/ppc/ira.py b/miasm2/arch/ppc/ira.py
new file mode 100644
index 00000000..2459c0e4
--- /dev/null
+++ b/miasm2/arch/ppc/ira.py
@@ -0,0 +1,47 @@
+from miasm2.expression.expression import ExprAff, ExprOp
+from miasm2.ir.ir import AssignBlock
+from miasm2.ir.analysis import ira
+from miasm2.arch.ppc.sem import ir_ppc32b
+
+
+class ir_a_ppc32b(ir_ppc32b, ira):
+
+    def __init__(self, *args):
+        super(ir_a_ppc32b, self).__init__(*args)
+        self.ret_reg = self.arch.regs.R3
+
+    # for test XXX TODO
+    def set_dead_regs(self, irblock):
+        pass
+
+    def get_out_regs(self, _):
+        return set([self.ret_reg, self.sp])
+
+    def add_unused_regs(self):
+        leaves = [self.blocks[label] for label in self.g.leafs()]
+        for irblock in leaves:
+            self.set_dead_regs(irblock)
+
+    def pre_add_instr(self, block, instr, assignments, ir_blocks_all, gen_pc_update):
+        """Replace function call with corresponding call effects,
+        inside the IR block"""
+        if not instr.is_subcall():
+            return False
+        call_effects = self.call_effects(instr.getdstflow(None)[0], instr)
+        assignments+= call_effects
+        return True
+
+    def sizeof_char(self):
+        return 8
+
+    def sizeof_short(self):
+        return 16
+
+    def sizeof_int(self):
+        return 32
+
+    def sizeof_long(self):
+        return 32
+
+    def sizeof_pointer(self):
+        return 32
diff --git a/miasm2/arch/ppc/jit.py b/miasm2/arch/ppc/jit.py
new file mode 100644
index 00000000..9134e032
--- /dev/null
+++ b/miasm2/arch/ppc/jit.py
@@ -0,0 +1,70 @@
+from miasm2.jitter.jitload import jitter, named_arguments
+from miasm2.core import asmblock
+from miasm2.arch.ppc.sem import ir_ppc32b
+import struct
+
+import logging
+
+log = logging.getLogger('jit_ppc')
+hnd = logging.StreamHandler()
+hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
+log.addHandler(hnd)
+log.setLevel(logging.CRITICAL)
+
+class jitter_ppc32b(jitter):
+    max_reg_arg = 8
+
+    def __init__(self, *args, **kwargs):
+        super(jitter_ppc32b, self).__init__(ir_ppc32b(asmblock.AsmSymbolPool()),
+                                            *args, **kwargs)
+        self.vm.set_big_endian()
+
+    def push_uint32_t(self, v):
+        self.cpu.R1 -= 4
+        self.vm.set_mem(self.cpu.R1, struct.pack(">I", v))
+
+    def pop_uint32_t(self):
+        x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1, 4))[0]
+        self.cpu.R1 += 4
+        return x
+
+    def get_stack_arg(self, n):
+        x = struct.unpack(">I", self.vm.get_mem(self.cpu.R1 + 8 + 4 * n, 4))[0]
+        return x
+
+    @named_arguments
+    def func_args_systemv(self, n_args):
+        args = [self.get_arg_n_systemv(i) for i in xrange(n_args)]
+        ret_ad = self.cpu.LR
+        return ret_ad, args
+
+    def func_ret_systemv(self, ret_addr, ret_value1=None, ret_value2=None):
+        self.pc = self.cpu.PC = ret_addr
+        if ret_value1 is not None:
+            self.cpu.R3 = ret_value1
+        if ret_value2 is not None:
+            self.cpu.R4 = ret_value2
+        return True
+
+    def func_prepare_systemv(self, ret_addr, *args):
+        for index in xrange(min(len(args), self.max_reg_arg)):
+            setattr(self.cpu, 'R%d' % (index + 3), args[index])
+        for index in xrange(len(args) - 1, self.max_reg_arg - 1, -1):
+            self.push_uint32_t(args[index])
+
+        # reserve room for LR save word and backchain
+        self.cpu.R1 -= 8
+
+        self.cpu.LR = ret_addr
+
+    def get_arg_n_systemv(self, index):
+        if index < self.max_reg_arg:
+            arg = getattr(self.cpu, 'R%d' % (index + 3))
+        else:
+            arg = self.get_stack_arg(index - self.max_reg_arg)
+        return arg
+
+
+    def init_run(self, *args, **kwargs):
+        jitter.init_run(self, *args, **kwargs)
+        self.cpu.PC = self.pc
diff --git a/miasm2/arch/ppc/regs.py b/miasm2/arch/ppc/regs.py
new file mode 100644
index 00000000..70b49f82
--- /dev/null
+++ b/miasm2/arch/ppc/regs.py
@@ -0,0 +1,59 @@
+
+from miasm2.expression.expression import *
+from miasm2.core.cpu import gen_reg, gen_regs
+
+exception_flags = ExprId('exception_flags', 32)
+spr_access = ExprId('spr_access', 32)
+
+reserve = ExprId('reserve', 1)
+reserve_address = ExprId('reserve_address', 32)
+
+SPR_ACCESS_IS_WRITE = 0x80000000
+SPR_ACCESS_SPR_MASK = 0x000003FF
+SPR_ACCESS_SPR_OFF  = 0
+SPR_ACCESS_GPR_MASK = 0x0001F000
+SPR_ACCESS_GPR_OFF  = 12
+
+gpregs_str = ["R%d" % i for i in xrange(32)]
+gpregs_expr, gpregs_init, gpregs = gen_regs(gpregs_str, globals(), 32)
+
+crfregs_str = ["CR%d" % i for i in xrange(8)]
+crfregs_expr, crfregs_init, crfregs = gen_regs(crfregs_str, globals(), 4)
+
+crfbitregs_str = ["CR%d_%s" % (i, flag) for i in xrange(8)
+                  for flag in ['LT', 'GT', 'EQ', 'SO'] ]
+crfbitregs_expr, crfbitregs_init, crfbitregs = gen_regs(crfbitregs_str,
+                                                        globals(), 1)
+
+xerbitregs_str = ["XER_%s" % field for field in ['SO', 'OV', 'CA'] ]
+xerbitregs_expr, xerbitregs_init, xerbitregs = gen_regs(xerbitregs_str,
+                                                        globals(), 1)
+
+xerbcreg_str = ["XER_BC"]
+xerbcreg_expr, xerbcreg_init, xerbcreg = gen_regs(xerbcreg_str,
+                                                  globals(), 7)
+
+
+otherregs_str = ["PC", "CTR", "LR" ]
+otherregs_expr, otherregs_init, otherregs = gen_regs(otherregs_str,
+                                                     globals(), 32)
+
+superregs_str = (["SPRG%d" % i for i in xrange(4)] +
+                 ["SRR%d" % i for i in xrange(2)] +
+                 ["DAR", "DSISR", "MSR", "PIR", "PVR",
+                  "DEC", "TBL", "TBU"])
+superregs_expr, superregs_init, superregs = gen_regs(superregs_str,
+                                                     globals(), 32)
+
+regs_flt_expr = []
+
+all_regs_ids = (gpregs_expr + crfbitregs_expr + xerbitregs_expr +
+                xerbcreg_expr + otherregs_expr + superregs_expr +
+                [ exception_flags, spr_access, reserve, reserve_address ])
+all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids])
+all_regs_ids_init = [ExprId("%s_init" % x.name, x.size) for x in all_regs_ids]
+all_regs_ids_no_alias = all_regs_ids[:]
+
+regs_init = {}
+for i, r in enumerate(all_regs_ids):
+    regs_init[r] = all_regs_ids_init[i]
diff --git a/miasm2/arch/ppc/sem.py b/miasm2/arch/ppc/sem.py
new file mode 100644
index 00000000..76a1a27e
--- /dev/null
+++ b/miasm2/arch/ppc/sem.py
@@ -0,0 +1,921 @@
+import miasm2.expression.expression as expr
+from miasm2.ir.ir import AssignBlock, IntermediateRepresentation, IRBlock
+from miasm2.arch.ppc.arch import mn_ppc
+from miasm2.arch.ppc.regs import *
+from miasm2.core.sembuilder import SemBuilder
+from miasm2.jitter.csts import *
+
+spr_dict = {
+    8: LR, 9: CTR, 18: DSISR, 19: DAR,
+    22: DEC, 26: SRR0, 27: SRR1,
+    272: SPRG0, 273: SPRG0, 274: SPRG1, 275: SPRG2, 276: SPRG3,
+    284: TBL, 285: TBU, 287: PVR, 1023: PIR
+}
+
+crf_dict = dict((ExprId("CR%d" % i, 4),
+                 dict( (bit, ExprId("CR%d_%s" % (i, bit), 1))
+                       for bit in ['LT', 'GT', 'EQ', 'SO' ] ))
+                for i in xrange(8) )
+
+ctx = { 'crf_dict': crf_dict, 'spr_dict': spr_dict }
+ctx.update(all_regs_ids_byname)
+sbuild = SemBuilder(ctx)
+
+def mn_compute_flags(rvalue, overflow_expr=None):
+    ret = []
+    ret.append(ExprAff(CR0_LT, rvalue.msb()))
+    ret.append(ExprAff(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1),
+                                         ExprInt(0, 1)) & ~rvalue.msb())))
+    ret.append(ExprAff(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1),
+                                        ExprInt(1, 1))))
+    if overflow_expr != None:
+        ret.append(ExprAff(CR0_SO, XER_SO | overflow_expr))
+    else:
+        ret.append(ExprAff(CR0_SO, XER_SO))
+
+    return ret
+
+def mn_do_add(ir, instr, arg1, arg2, arg3):
+    assert instr.name[0:3] == 'ADD'
+
+    flags_update = []
+
+    has_dot = False
+    has_c = False
+    has_e = False
+    has_o = False
+
+    for l in instr.name[3:]:
+        if l == '.':
+            has_dot = True
+        elif l == 'C':
+            has_c = True
+        elif l == 'E':
+            has_e = True
+        elif l == 'O':
+            has_o = True
+        elif l == 'I' or l == 'M' or l == 'S' or l == 'Z':
+            pass	# Taken care of earlier
+        else:
+            assert False
+
+    rvalue = arg2 + arg3
+
+    if has_e:
+        rvalue = rvalue + XER_CA.zeroExtend(32)
+
+    over_expr = None
+    if has_o:
+        msb1 = arg2.msb()
+        msb2 = arg3.msb()
+        msba = rvalue.msb()
+        over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba)
+        flags_update.append(ExprAff(XER_OV, over_expr))
+        flags_update.append(ExprAff(XER_SO, XER_SO | over_expr))
+
+    if has_dot:
+        flags_update += mn_compute_flags(rvalue, over_expr)
+
+    if has_c or has_e:
+        carry_expr = (((arg2 ^ arg3) ^ rvalue) ^
+                      ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb()
+        flags_update.append(ExprAff(XER_CA, carry_expr))
+
+    return ([ ExprAff(arg1, rvalue) ] + flags_update), []
+
+def mn_do_and(ir, instr, ra, rs, arg2):
+    if len(instr.name) > 3 and instr.name[3] == 'C':
+        oarg = ~arg2
+    else:
+        oarg = arg2
+
+    rvalue = rs & oarg
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_cntlzw(ir, instr, ra, rs):
+    rvalue = ExprCond(rs, ExprInt(31, 32) - ExprOp('bsr', rs), ExprInt(32, 32))
+
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def crbit_to_reg(bit):
+    bit = bit.arg.arg
+    crid = bit / 4
+    bitname = [ 'LT', 'GT', 'EQ', 'SO' ][bit % 4]
+    return all_regs_ids_byname["CR%d_%s" % (crid, bitname)]
+
+def mn_do_cr(ir, instr, crd, cra, crb):
+    a = crbit_to_reg(cra)
+    b = crbit_to_reg(crb)
+    d = crbit_to_reg(crd)
+
+    op = instr.name[2:]
+
+    if op == 'AND':
+        r = a & b
+    elif op == 'ANDC':
+        r = a & ~b
+    elif op == 'EQV':
+        r = ~(a ^ b)
+    elif op == 'NAND':
+        r = ~(a & b)
+    elif op == 'NOR':
+        r = ~(a | b)
+    elif op == 'OR':
+        r = a | b
+    elif op == 'ORC':
+        r = a | ~b
+    elif op == 'XOR':
+        r = a ^ b
+    else:
+        raise "Unknown operation on CR"
+    return [ ExprAff(d, r) ], []
+
+def mn_do_div(ir, instr, rd, ra, rb):
+    assert instr.name[0:4] == 'DIVW'
+
+    flags_update = []
+
+    has_dot = False
+    has_c = False
+    has_o = False
+    has_u = False
+
+    for l in instr.name[3:]:
+        if l == '.':
+            has_dot = True
+        elif l == 'C':
+            has_c = True
+        elif l == 'O':
+            has_o = True
+        elif l == 'U':
+            has_u = True
+        elif l == 'W':
+            pass
+        else:
+            assert False
+
+    if has_u:
+        op = 'udiv'
+    else:
+        op = 'idiv'
+
+    rvalue = ExprOp(op, ra, rb)
+
+    over_expr = None
+    if has_o:
+        over_expr = ExprCond(rb, ExprInt(0, 1), ExprInt(1, 1))
+        if not has_u:
+            over_expr = over_expr | (ExprCond(ra ^ 0x80000000, ExprInt(0, 1),
+                                              ExprInt(1, 1)) &
+                                     ExprCond(rb ^ 0xFFFFFFFF, ExprInt(0, 1),
+                                              ExprInt(1, 1)))
+        flags_update.append(ExprAff(XER_OV, over_expr))
+        flags_update.append(ExprAff(XER_SO, XER_SO | over_expr))
+
+    if has_dot:
+        flags_update += mn_compute_flags(rvalue, over_expr)
+
+    return ([ ExprAff(rd, rvalue) ] + flags_update), []
+    
+
+def mn_do_eqv(ir, instr, ra, rs, rb):
+    rvalue = ~(rs ^ rb)
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_exts(ir, instr, ra, rs):
+    if instr.name[4] == 'B':
+        size = 8
+    elif instr.name[4] == 'H':
+        size = 16
+    else:
+        assert False
+
+    rvalue = rs[0:size].signExtend(32)
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def byte_swap(expr):
+    nbytes = expr.size / 8
+    bytes = [ expr[i*8:i*8+8] for i in xrange(nbytes - 1, -1, -1) ]
+    return ExprCompose(bytes)
+
+def mn_do_load(ir, instr, arg1, arg2, arg3=None):
+    assert instr.name[0] == 'L'
+
+    ret = []
+
+    if instr.name[1] == 'M':
+        return mn_do_lmw(ir, instr, arg1, arg2)
+    elif instr.name[1] == 'S':
+        raise RuntimeError("LSWI, and LSWX need implementing")
+        pass # XXX
+
+    size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]]
+
+    has_a = False
+    has_b = False
+    has_u = False
+    is_lwarx = False
+
+    for l in instr.name[2:]:
+        if l == 'A':
+            has_a = True
+        elif l == 'B':
+            has_b = True
+        elif l == 'U':
+            has_u = True
+        elif l == 'X' or l == 'Z':
+            pass	# Taken care of earlier
+        elif l == 'R' and not has_b:
+            is_lwarx = True
+        else:
+            assert False
+
+    if arg3 is None:
+        assert isinstance(arg2, ExprMem)
+
+        address = arg2.arg
+    else:
+        address = arg2 + arg3
+
+    src = ExprMem(address, size)
+
+    if has_b:
+        src = byte_swap(src)
+
+    if has_a:
+        src = src.signExtend(32)
+    else:
+        src = src.zeroExtend(32)
+
+    ret.append(ExprAff(arg1, src))
+    if has_u:
+        if arg3 is None:
+            ret.append(ExprAff(arg2.arg.args[0], address))
+        else:
+            ret.append(ExprAff(arg2, address))
+
+    if is_lwarx:
+        ret.append(ExprAff(reserve, ExprInt(1, 1)))
+        ret.append(ExprAff(reserve_address, address))	# XXX should be the PA
+
+    return ret, []
+
+def mn_do_lmw(ir, instr, rd, src):
+    ret = []
+    address = src.arg
+    ri = int(rd.name[1:],10)
+    i = 0
+    while ri <= 31:
+        ret.append(ExprAff(all_regs_ids_byname["R%d" % ri],
+                           ExprMem(address + ExprInt(i, 32), 32)))
+        ri += 1
+        i += 4
+
+    return ret, []
+
+def mn_do_lswi(ir, instr, rd, ra, nb):
+    if nb == 0:
+        nb = 32
+    i = 32
+    raise "%r not implemented" % instr
+
+def mn_do_lswx(ir, instr, rd, ra, nb):
+    raise "%r not implemented" % instr
+
+def mn_do_mcrf(ir, instr, crfd, crfs):
+    ret = []
+
+    for bit in [ 'LT', 'GT', 'EQ', 'SO' ]:
+        d = all_regs_ids_byname["%s_%s" % (crfd, bit)]
+        s = all_regs_ids_byname["%s_%s" % (crfs, bit)]
+        ret.append(ExprAff(d, s))
+
+    return ret, []
+
+def mn_do_mcrxr(ir, instr, crfd):
+    ret = []
+
+    for (bit, val) in [ ('LT', XER_SO), ('GT', XER_OV), ('EQ', XER_CA),
+                        ('SO', ExprInt(0, 1)) ]:
+        ret.append(ExprAff(all_regs_ids_byname["%s_%s" % (crfd, bit)], val))
+
+    return ret, []
+
+def mn_do_mfcr(ir, instr, rd):
+    return ([ ExprAff(rd, ExprCompose(*[ all_regs_ids_byname["CR%d_%s" % (i, b)]
+                                        for i in xrange(7, -1, -1)
+                                        for b in ['SO', 'EQ', 'GT', 'LT']]))],
+            [])
+
+@sbuild.parse
+def mn_mfmsr(rd):
+    rd = MSR
+
+def mn_mfspr(ir, instr, arg1, arg2):
+    sprid = arg2.arg.arg
+    gprid = int(arg1.name[1:])
+    if sprid in spr_dict:
+        return [ ExprAff(arg1, spr_dict[sprid]) ], []
+    elif sprid == 1:		# XER
+        return [ ExprAff(arg1, ExprCompose(XER_BC, ExprInt(0, 22),
+                                           XER_CA, XER_OV, XER_SO)) ], []
+    else:
+        return [ ExprAff(spr_access,
+                         ExprInt(((sprid << SPR_ACCESS_SPR_OFF) |
+                                    (gprid << SPR_ACCESS_GPR_OFF)), 32)),
+                 ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], []
+
+def mn_mtcrf(ir, instr, crm, rs):
+    ret = []
+
+    for i in xrange(8):
+        if crm.arg.arg & (1 << (7 - i)):
+            j = (28 - 4 * i) + 3
+            for b in ['LT', 'GT', 'EQ', 'SO']:
+                ret.append(ExprAff(all_regs_ids_byname["CR%d_%s" % (i, b)],
+                                   rs[j:j+1]))
+                j -= 1
+
+    return ret, []
+
+def mn_mtmsr(ir, instr, rs):
+    print "%08x: MSR assigned" % instr.offset
+    return [ ExprAff(MSR, rs) ], []
+
+def mn_mtspr(ir, instr, arg1, arg2):
+    sprid = arg1.arg.arg
+    gprid = int(arg2.name[1:])
+    if sprid in spr_dict:
+        return [ ExprAff(spr_dict[sprid], arg2) ], []
+    elif sprid == 1:		# XER
+        return [ ExprAff(XER_SO, arg2[31:32]),
+                 ExprAff(XER_OV, arg2[30:31]),
+                 ExprAff(XER_CA, arg2[29:30]),
+                 ExprAff(XER_BC, arg2[0:7]) ], []
+    else:
+        return [ ExprAff(spr_access,
+                         ExprInt(((sprid << SPR_ACCESS_SPR_OFF) |
+                                    (gprid << SPR_ACCESS_GPR_OFF) |
+                                    SPR_ACCESS_IS_WRITE), 32)),
+                 ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], []
+
+def mn_do_mul(ir, instr, rd, ra, arg2):
+    variant = instr.name[3:]
+    if variant[-1] == '.':
+        variant = variant[:-2]
+
+    if variant == 'HW':
+        v1 = ra.signExtend(64)
+        v2 = arg2.signExtend(64)
+        shift = 32
+    elif variant == 'HWU':
+        v1 = ra.zeroExtend(64)
+        v2 = arg2.zeroExtend(64)
+        shift = 32
+    else:
+        v1 = ra
+        v2 = arg2
+        shift = 0
+
+    rvalue = ExprOp('*', v1, v2)
+    if shift != 0:
+        rvalue = rvalue[shift : shift + 32]
+
+    ret = [ ExprAff(rd, rvalue) ]
+
+    over_expr = None
+    if variant[-1] == 'O':
+        over_expr = ExprCond((rvalue.signExtend(64) ^
+                              ExprOp('*', v1.signExtend(64),
+                                     v2.signExtend(64))),
+                             ExprInt(1, 1), ExprInt(0, 1))
+        ret.append(ExprAff(XER_OV, over_expr))
+        ret.append(ExprAff(XER_SO, XER_SO | over_expr))
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue, over_expr)
+
+    return ret, []
+
+def mn_do_nand(ir, instr, ra, rs, rb):
+    rvalue = ~(rs & rb)
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_neg(ir, instr, rd, ra):
+    rvalue = -ra
+    ret = [ ExprAff(ra, rvalue) ]
+    has_o = False
+
+    over_expr = None
+    if instr.name[-1] == 'O' or instr.name[-2] == 'O':
+        has_o = True
+        over_expr = ExprCond(ra ^ ExprInt(0x80000000, 32),
+                             ExprInt(0, 1), ExprInt(1, 1))
+        ret.append(ExprAff(XER_OV, over_expr))
+        ret.append(ExprAff(XER_SO, XER_SO | over_expr))
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue, over_expr)
+
+    return ret, []
+
+def mn_do_nor(ir, instr, ra, rs, rb):
+
+    rvalue = ~(rs | rb)
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_or(ir, instr, ra, rs, arg2):
+    if len(instr.name) > 2 and instr.name[2] == 'C':
+        oarg = ~arg2
+    else:
+        oarg = arg2
+
+    rvalue = rs | oarg
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_rfi(ir, instr):
+    dest = ExprCompose(ExprInt(0, 2), SRR0[2:32])
+    ret = [ ExprAff(MSR, (MSR &
+                          ~ExprInt(0b1111111101110011, 32) |
+                          ExprCompose(SRR1[0:2], ExprInt(0, 2),
+                                      SRR1[4:7], ExprInt(0, 1), 
+                                      SRR1[8:16], ExprInt(0, 16)))),
+            ExprAff(PC, dest),
+            ExprAff(ir.IRDst, dest) ]
+    return ret, []
+
+def mn_do_rotate(ir, instr, ra, rs, shift, mb, me):
+    r = ExprOp('<<<', rs, shift)
+    if mb <= me:
+        m = ExprInt(((1 << (32 - mb)) - 1) & ~((1 << (32 - me - 1)) - 1), 32)
+    else:
+        m = ExprInt(((1 << (32 - mb)) - 1) | ~((1 << (32 - me - 1)) - 1), 32)
+    rvalue = r & m
+    if instr.name[0:6] == 'RLWIMI':
+        rvalue = rvalue | (ra & ~m)
+
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_slw(ir, instr, ra, rs, rb):
+
+    rvalue = ExprCond(rb[5:6], ExprInt(0, 32),
+                      ExprOp('<<', rs, rb & ExprInt(0b11111, 32)))
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_sraw(ir, instr, ra, rs, rb):
+    rvalue = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32),
+                      ExprOp('a>>', rs, rb & ExprInt(0b11111, 32)))
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32),
+                    (ExprInt(0xFFFFFFFF, 32) >>
+                     (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32)))))
+    ret.append(ExprAff(XER_CA, rs.msb() &
+                       ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1))))
+
+    return ret, []
+
+def mn_do_srawi(ir, instr, ra, rs, imm):
+    rvalue = ExprOp('a>>', rs, imm)
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    mask = ExprInt(0xFFFFFFFF >> (32 - imm.arg.arg), 32)
+
+    ret.append(ExprAff(XER_CA, rs.msb() &
+                       ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1))))
+
+    return ret, []
+
+def mn_do_srw(ir, instr, ra, rs, rb):
+    rvalue = rs >> (rb & ExprInt(0b11111, 32))
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+def mn_do_stmw(ir, instr, rs, dest):
+    ret = []
+    address = dest.arg
+    ri = int(rs.name[1:],10)
+    i = 0
+    while ri <= 31:
+        ret.append(ExprAff(ExprMem(address + ExprInt(i,32), 32),
+                           all_regs_ids_byname["R%d" % ri]))
+        ri += 1
+        i += 4
+
+    return ret, []
+
+def mn_do_store(ir, instr, arg1, arg2, arg3=None):
+    assert instr.name[0:2] == 'ST'
+
+    ret = []
+    additional_ir = []
+
+    if instr.name[2] == 'S':
+        raise RuntimeError("STSWI, and STSWX need implementing")
+        pass # XXX
+
+    size = {'B': 8, 'H': 16, 'W': 32}[instr.name[2]]
+
+    has_b = False
+    has_u = False
+    is_stwcx = False
+
+    for l in instr.name[3:]:
+        if l == 'B' or l == 'R':
+            has_b = True
+        elif l == 'U':
+            has_u = True
+        elif l == 'X' or l == 'Z':
+            pass	# Taken care of earlier
+        elif l == 'C' or l == '.':
+            is_stwcx = True
+        else:
+            assert False
+
+    if arg3 is None:
+        assert isinstance(arg2, ExprMem)
+
+        address = arg2.arg
+    else:
+        address = arg2 + arg3
+
+    dest = ExprMem(address, size)
+
+    src = arg1[0:size]
+    if has_b:
+        src = byte_swap(src)
+
+    ret.append(ExprAff(dest, src))
+    if has_u:
+        if arg3 is None:
+            ret.append(ExprAff(arg2.arg.args[0], address))
+        else:
+            ret.append(ExprAff(arg2, address))
+
+    if is_stwcx:
+        lbl_do = ExprId(ir.gen_label(), ir.IRDst.size)
+        lbl_dont = ExprId(ir.gen_label(), ir.IRDst.size)
+        lbl_next = ExprId(ir.get_next_label(instr), ir.IRDst.size)
+        flags = [ ExprAff(CR0_LT, ExprInt(0,1)),
+                  ExprAff(CR0_GT, ExprInt(0,1)),
+                  ExprAff(CR0_SO, XER_SO)]
+        ret += flags
+        ret.append(ExprAff(CR0_EQ, ExprInt(1,1)))
+        ret.append(ExprAff(ir.IRDst, lbl_next))
+        dont = flags + [ ExprAff(CR0_EQ, ExprInt(0,1)),
+                         ExprAff(ir.IRDst, lbl_next) ]
+        additional_ir = [ IRBlock(lbl_do.name, [ AssignBlock(ret) ]),
+                          IRBlock(lbl_dont.name, [ AssignBlock(dont) ]) ]
+        ret = [ ExprAff(reserve, ExprInt(0, 1)),
+                ExprAff(ir.IRDst, ExprCond(reserve, lbl_do, lbl_dont)) ]
+
+    return ret, additional_ir
+
+def mn_do_sub(ir, instr, arg1, arg2, arg3):
+    assert instr.name[0:4] == 'SUBF'
+
+    flags_update = []
+
+    has_dot = False
+    has_c = False
+    has_e = False
+    has_o = False
+
+    for l in instr.name[4:]:
+        if l == '.':
+            has_dot = True
+        elif l == 'C':
+            has_c = True
+        elif l == 'E':
+            has_e = True
+        elif l == 'O':
+            has_o = True
+        elif l == 'I' or l == 'M' or l == 'S' or l == 'Z':
+            pass	# Taken care of earlier
+        else:
+            assert False
+
+    if has_e:
+        arg3 = arg3 + XER_CA.zeroExtend(32)
+        arg2 = arg2 + ExprInt(1, 32)
+
+    rvalue = arg3 - arg2
+
+    over_expr = None
+    if has_o:
+        msb1 = arg2.msb()
+        msb2 = arg3.msb()
+        msba = rvalue.msb()
+        over_expr = (msb1 ^ msb2) & (msb1 ^ msba)
+        flags_update.append(ExprAff(XER_OV, over_expr))
+        flags_update.append(ExprAff(XER_SO, XER_SO | over_expr))
+
+    if has_dot:
+        flags_update += mn_compute_flags(rvalue, over_expr)
+
+    if has_c or has_e:
+        carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^
+                       ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb())
+        flags_update.append(ExprAff(XER_CA, ~carry_expr))
+
+    return ([ ExprAff(arg1, rvalue) ] + flags_update), []
+
+def mn_do_xor(ir, instr, ra, rs, rb):
+    rvalue = rs ^ rb
+    ret = [ ExprAff(ra, rvalue) ]
+
+    if instr.name[-1] == '.':
+        ret += mn_compute_flags(rvalue)
+
+    return ret, []
+
+@sbuild.parse
+def mn_b(arg1):
+    PC = arg1
+    ir.IRDst = arg1
+
+@sbuild.parse
+def mn_bl(arg1):
+    LR = ExprId(ir.get_next_instr(instr), 32)
+    PC = arg1
+    ir.IRDst = arg1
+
+def mn_get_condition(instr):
+    bit = instr.additional_info.bi & 0b11
+    cr = instr.args[0].name
+    return all_regs_ids_byname[cr + '_' + ['LT', 'GT', 'EQ', 'SO'][bit]]
+
+def mn_do_cond_branch(ir, instr, dest):
+    bo = instr.additional_info.bo
+    bi = instr.additional_info.bi
+    ret = []
+    if not (bo & 0b00100):
+        ret.append(ExprAff(CTR, CTR - ExprInt(1, 32)))
+    if (bo & 0b10100) == 0b10100:
+        ctr_cond = True
+    else:
+        ctr_cond = ExprCond(CTR ^ ExprInt(1, 32), ExprInt(1, 1), ExprInt(0, 1))
+        if bo & 0b00010:
+            ctr_cond = ~ctr_cond
+
+    if (bo & 0b10000):
+        cond_cond = True
+    else:
+        cond_cond = mn_get_condition(instr)
+        if not (bo & 0b01000):
+            cond_cond = ~cond_cond
+
+    if ctr_cond != True or cond_cond != True:
+        if ctr_cond != True:
+            condition = ctr_cond
+            if cond_cond != True:
+                condition = condition & cond_cond
+        else:
+            condition = cond_cond
+        dest_expr = ExprCond(condition, dest,
+                             ExprId(ir.get_next_instr(instr), 32))
+    else:
+        dest_expr = dest
+
+    if instr.name[-1] == 'L' or instr.name[-2:-1] == 'LA':
+        ret.append(ExprAff(LR, ExprId(ir.get_next_instr(instr), 32)))
+
+    ret.append(ExprAff(PC, dest_expr))
+    ret.append(ExprAff(ir.IRDst, dest_expr))
+
+    return ret, []
+
+def mn_do_nop_warn(ir, instr, *args):
+    print "Warning, instruction %s implemented as NOP" % instr
+    return [], []
+
+@sbuild.parse
+def mn_cmp_signed(arg1, arg2, arg3):
+    crf_dict[arg1]['LT'] = ((arg2 - arg3) ^
+                            ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb()
+    crf_dict[arg1]['GT'] = ((arg3 - arg2) ^
+                            ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))).msb()
+    crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1)
+    crf_dict[arg1]['SO'] = XER_SO
+
+@sbuild.parse
+def mn_cmp_unsigned(arg1, arg2, arg3):
+    crf_dict[arg1]['LT'] = (((arg2 - arg3) ^
+                             ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^
+                            arg2 ^ arg3).msb()
+    crf_dict[arg1]['GT'] = (((arg3 - arg2) ^
+                             ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))) ^
+                            arg2 ^ arg3).msb()
+    crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1)
+    crf_dict[arg1]['SO'] = XER_SO
+
+def mn_nop(ir, instr, *args):
+    return [], []
+
+@sbuild.parse
+def mn_or(arg1, arg2, arg3):
+    arg1 = arg2 | arg3
+
+@sbuild.parse
+def mn_assign(arg1, arg2):
+    arg2 = arg1
+
+def mn_stb(ir, instr, arg1, arg2):
+    dest = ExprMem(arg2.arg, 8)
+    return [ExprAff(dest, ExprSlice(arg1, 0, 8))], []
+
+@sbuild.parse
+def mn_stwu(arg1, arg2):
+    arg2 = arg1
+    arg1 = arg2.arg
+
+sem_dir = {
+    'B': mn_b,
+    'BA': mn_b,
+    'BL': mn_bl,
+    'BLA': mn_bl,
+    'CMPLW': mn_cmp_unsigned,
+    'CMPLWI': mn_cmp_unsigned,
+    'CMPW': mn_cmp_signed,
+    'CMPWI': mn_cmp_signed,
+    'CNTLZW': mn_do_cntlzw,
+    'CNTLZW.': mn_do_cntlzw,
+    'ECIWX': mn_do_nop_warn,
+    'ECOWX': mn_do_nop_warn,
+    'EIEIO': mn_do_nop_warn,
+    'EQV': mn_do_eqv,
+    'EQV.': mn_do_eqv,
+    'ICBI': mn_do_nop_warn,
+    'ISYNC': mn_do_nop_warn,
+    'MCRF': mn_do_mcrf,
+    'MCRXR': mn_do_mcrxr,
+    'MFCR': mn_do_mfcr,
+    'MFMSR': mn_mfmsr,
+    'MFSPR': mn_mfspr,
+    'MFSR': mn_do_nop_warn,
+    'MFSRIN': mn_do_nop_warn,
+    'MFTB': mn_mfmsr,
+    'MTCRF': mn_mtcrf,
+    'MTMSR': mn_mtmsr,
+    'MTSPR': mn_mtspr,
+    'MTSR': mn_do_nop_warn,
+    'MTSRIN': mn_do_nop_warn,
+    'NAND': mn_do_nand,
+    'NAND.': mn_do_nand,
+    'NOR': mn_do_nor,
+    'NOR.': mn_do_nor,
+    'RFI': mn_do_rfi,
+    'SC': mn_do_nop_warn,
+    'SLW': mn_do_slw,
+    'SLW.': mn_do_slw,
+    'SRAW': mn_do_sraw,
+    'SRAW.': mn_do_sraw,
+    'SRAWI': mn_do_srawi,
+    'SRAWI.': mn_do_srawi,
+    'SRW': mn_do_srw,
+    'SRW.': mn_do_srw,
+    'SYNC': mn_do_nop_warn,
+    'TLBIA': mn_do_nop_warn,
+    'TLBIE': mn_do_nop_warn,
+    'TLBSYNC': mn_do_nop_warn,
+    'TW': mn_do_nop_warn,
+    'TWI': mn_do_nop_warn,
+}
+
+
+class ir_ppc32b(IntermediateRepresentation):
+
+    def __init__(self, symbol_pool=None):
+        super(ir_ppc32b, self).__init__(mn_ppc, 'b', symbol_pool)
+        self.pc = mn_ppc.getpc()
+        self.sp = mn_ppc.getsp()
+        self.IRDst = expr.ExprId('IRDst', 32)
+
+    def get_ir(self, instr):
+        args = instr.args[:]
+        if instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]:
+            args[2] = ExprInt(args[2].arg << 16, 32)
+        if instr.name[0:3] == 'ADD':
+            if instr.name[0:4] == 'ADDZ':
+                last_arg = ExprInt(0, 32)
+            elif instr.name[0:4] == 'ADDM':
+                last_arg = ExprInt(0xFFFFFFFF, 32)
+            else:
+                last_arg = args[2]
+            instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1],
+                                           last_arg)
+        elif instr.name[0:3] == 'AND':
+            instr_ir, extra_ir = mn_do_and(self, instr, *args)
+        elif instr.additional_info.bo_bi_are_defined:
+            name = instr.name
+            if name[-1] == '+' or name[-1] == '-':
+                name = name[0:-1]
+            if name[-3:] == 'CTR' or name[-4:] == 'CTRL':
+                arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32])
+            elif name[-2:] == 'LR' or name[-3:] == 'LRL':
+                arg1 = ExprCompose(ExprInt(0, 2), LR[2:32])
+            else:
+                arg1 = args[1]
+            instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1)
+        elif instr.name[0:2] == 'CR':
+            instr_ir, extra_ir = mn_do_cr(self, instr, *args)
+        elif instr.name[0:3] == 'DCB':
+            instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args)
+        elif instr.name[0:3] == 'DIV':
+            instr_ir, extra_ir = mn_do_div(self, instr, *args)
+        elif instr.name[0:4] == 'EXTS':
+            instr_ir, extra_ir = mn_do_exts(self, instr, *args)
+        elif instr.name[0] == 'L':
+            instr_ir, extra_ir = mn_do_load(self, instr, *args)
+        elif instr.name[0:3] == 'MUL':
+            instr_ir, extra_ir = mn_do_mul(self, instr, *args)
+        elif instr.name[0:3] == 'NEG':
+            instr_ir, extra_ir = mn_do_neg(self, instr, *args)
+        elif instr.name[0:2] == 'OR':
+            instr_ir, extra_ir = mn_do_or(self, instr, *args)
+        elif instr.name[0:2] == 'RL':
+            instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1],
+                                              args[2], args[3].arg.arg,
+                                              args[4].arg.arg)
+        elif instr.name == 'STMW':
+            instr_ir, extra_ir = mn_do_stmw(self, instr, *args)
+        elif instr.name[0:2] == 'ST':
+            instr_ir, extra_ir = mn_do_store(self, instr, *args)
+        elif instr.name[0:4] == 'SUBF':
+            if instr.name[0:5] == 'SUBFZ':
+                last_arg = ExprInt(0)
+            elif instr.name[0:5] == 'SUBFM':
+                last_arg = ExprInt(0xFFFFFFFF)
+            else:
+                last_arg = args[2]
+            instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1],
+                                           last_arg)
+        elif instr.name[0:3] == 'XOR':
+            instr_ir, extra_ir = mn_do_xor(self, instr, *args)
+        else:
+            instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args)
+
+        return instr_ir, extra_ir
+
+    def get_next_instr(self, instr):
+        l = self.symbol_pool.getby_offset_create(instr.offset  + 4)
+        return l
+
+    def get_next_break_label(self, instr):
+        l = self.symbol_pool.getby_offset_create(instr.offset  + 4)
+        return l
diff --git a/miasm2/jitter/Makefile b/miasm2/jitter/Makefile
index 7d43f28c..4bc96b0f 100644
--- a/miasm2/jitter/Makefile
+++ b/miasm2/jitter/Makefile
@@ -1,5 +1,5 @@
 all: vm_mngr.so Jit_x86.so Jittcc.so
-	
+
 
 vm_mngr.so: vm_mngr.c vm_mngr.h vm_mngr_py.c
 	gcc -I /usr/include/python2.7  -shared -fPIC vm_mngr.c vm_mngr_py.c -o vm_mngr.so
@@ -10,8 +10,11 @@ Jit_x86.so: arch/Jit_x86.c
 Jit_arm.so: arch/Jit_arm.c
 	gcc -I /usr/include/python2.7  -shared -fPIC arch/Jit_arm.c -o arch/Jit_arm.so
 
+Jit_ppc.so: arch/Jit_ppc.c
+	gcc -I /usr/include/python2.7  -shared -fPIC arch/Jit_ppc.c -o arch/Jit_ppc.so
+
 Jittcc.so: Jittcc.c
 	gcc -I /usr/include/python2.7  -shared -fPIC Jittcc.c -o Jittcc.so -ltcc
 
 clean:
-	rm vm_mngr.so Jittcc.so arch/Jit_x86.so
\ No newline at end of file
+	rm vm_mngr.so Jittcc.so arch/Jit_x86.so arch/Jit_arm.so arch/Jit_ppc.so
diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c
new file mode 100644
index 00000000..7ea5e88f
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_ppc32.c
@@ -0,0 +1,373 @@
+#include <Python.h>
+#include "structmember.h"
+#include <stdint.h>
+#include <inttypes.h>
+#include "../queue.h"
+#include "../vm_mngr.h"
+#include "../vm_mngr_py.h"
+#include "../JitCore.h"
+#include "JitCore_ppc32.h"
+
+reg_dict gpreg_dict[] = {
+#define JITCORE_PPC_REG_EXPAND(_name, _size)				\
+    { .name = #_name, .offset = offsetof(struct vm_cpu, _name) },
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+};
+
+PyObject* cpu_get_gpreg(JitCpu* self)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+#define JITCORE_PPC_REG_EXPAND(_name, _size) \
+    get_reg(_name);
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+    return dict;
+}
+
+
+
+PyObject *
+cpu_set_gpreg(JitCpu *self, PyObject *args) {
+    PyObject *dict;
+    PyObject *d_key, *d_value = NULL;
+    Py_ssize_t pos = 0;
+    uint64_t val;
+    unsigned int i;
+
+    if (!PyArg_ParseTuple(args, "O", &dict))
+	return NULL;
+    if(!PyDict_Check(dict))
+	RAISE(PyExc_TypeError, "arg must be dict");
+
+    while(PyDict_Next(dict, &pos, &d_key, &d_value)) {
+	int found = 0;
+
+	if(!PyString_Check(d_key))
+	    RAISE(PyExc_TypeError, "key must be str");
+
+	PyGetInt(d_value, val);
+
+	for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){
+	    if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name))
+		continue;
+	    *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val;
+	    found = 1;
+	    break;
+	}
+
+	if (found)
+	    continue;
+	fprintf(stderr, "unknown key: %s\n", PyString_AsString(d_key));
+	RAISE(PyExc_ValueError, "unknown reg");
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+PyObject *
+cpu_init_regs(JitCpu *self) {
+    memset(self->cpu, 0, sizeof(struct vm_cpu));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static void
+dump_gpreg(const char *name, uint32_t val, int *n) {
+    printf("%6s %.8" PRIX32"%c", name, val, (*n + 1) % 4 == 0? '\n':' ');
+    *n = (*n + 1) % 4;
+}
+
+void
+dump_gpregs(struct vm_cpu *vmcpu) {
+    int reg_num = 0;
+
+#define JITCORE_PPC_REG_EXPAND(_name, _size) \
+    dump_gpreg(#_name, vmcpu->_name, &reg_num);
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+    if ((reg_num % 4) != 0)
+      putchar('\n');
+}
+
+
+PyObject *
+cpu_dump_gpregs(JitCpu *self, PyObject *args) {
+
+    dump_gpregs(self->cpu);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject *
+cpu_set_exception(JitCpu *self, PyObject *args) {
+    PyObject *item1;
+    uint64_t i;
+
+    if (!PyArg_ParseTuple(args, "O", &item1))
+	return NULL;
+
+    PyGetInt(item1, i);
+
+    ((struct vm_cpu *)self->cpu)->exception_flags = i;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject *
+cpu_get_exception(JitCpu *self, PyObject *args) {
+    return PyLong_FromUnsignedLongLong(((struct vm_cpu *)self->cpu)->exception_flags);
+}
+
+static PyObject *
+cpu_get_spr_access(JitCpu *self, PyObject *args) {
+    return PyLong_FromUnsignedLongLong(((struct vm_cpu *) self->cpu)->spr_access);
+}
+
+void
+check_automod(JitCpu *jitcpu, uint64_t addr, uint64_t size) {
+    PyObject *result;
+
+    if (!(((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags & EXCEPT_CODE_AUTOMOD))
+	return;
+    result = PyObject_CallMethod(jitcpu->jitter, "automod_cb", "LL", addr, size);
+    Py_DECREF(result);
+}
+
+void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src)
+{
+	vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
+	check_automod(jitcpu, addr, 8);
+}
+
+void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src)
+{
+	vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
+	check_automod(jitcpu, addr, 16);
+}
+
+void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src)
+{
+	vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
+	check_automod(jitcpu, addr, 32);
+}
+
+void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src)
+{
+	vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
+	check_automod(jitcpu, addr, 64);
+}
+
+
+
+PyObject *
+vm_set_mem(JitCpu *self, PyObject *args) {
+   PyObject *py_addr;
+   PyObject *py_buffer;
+   Py_ssize_t py_length;
+
+   char *buffer;
+   uint64_t size;
+   uint64_t addr;
+   int ret = 0x1337;
+
+   if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer))
+       return NULL;
+
+   PyGetInt(py_addr, addr);
+
+   if(!PyString_Check(py_buffer))
+       RAISE(PyExc_TypeError,"arg must be str");
+
+   size = PyString_Size(py_buffer);
+   PyString_AsStringAndSize(py_buffer, &buffer, &py_length);
+
+   ret = vm_write_mem(&(((VmMngr*)self->pyvm)->vm_mngr), addr, buffer, size);
+   if (ret < 0)
+       RAISE(PyExc_TypeError,"arg must be str");
+   check_automod(self, addr, size*8);
+
+   Py_INCREF(Py_None);
+   return Py_None;
+}
+
+static PyMemberDef JitCpu_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef JitCpu_methods[] = {
+    {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"},
+    {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"},
+    {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"},
+    {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"},
+    {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"},
+    {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, "X"},
+    {"get_spr_access", (PyCFunction)cpu_get_spr_access, METH_VARARGS, "X"},
+    {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, "X"},
+    {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, "X"},
+    {NULL}  /* Sentinel */
+};
+
+static int
+JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) {
+    self->cpu = malloc(sizeof(struct vm_cpu));
+    if (self->cpu == NULL) {
+	fprintf(stderr, "cannot alloc struct vm_cpu\n");
+	exit(1);
+    }
+    return 0;
+}
+
+
+#define JITCORE_PPC_REG_EXPAND(_name, _size) \
+getset_reg_u32(_name);
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+PyObject *
+get_gpreg_offset_all(void) {
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+
+#define JITCORE_PPC_REG_EXPAND(_name, _size)				\
+    get_reg_off(_name);
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+    return dict;
+}
+
+int32_t
+idiv32(struct vm_cpu *cpu, int32_t a, int32_t b) {
+    if (b == 0)
+	return 0;
+
+    return a / b;
+}
+
+uint32_t
+udiv32(struct vm_cpu *cpu, uint32_t a, uint32_t b) {
+    if (b == 0)
+	return 0;
+
+    return a / b;
+}
+
+int32_t
+imod32(struct vm_cpu *cpu, int32_t a, int32_t b) {
+    if (b == 0)
+	return 0;
+
+    return a % b;
+}
+
+uint32_t
+umod32(struct vm_cpu *cpu, uint32_t a, uint32_t b) {
+    if (b == 0)
+	return 0;
+
+    return a % b;
+}
+
+static PyGetSetDef JitCpu_getseters[] = {
+    {"vmmngr",
+     (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr,
+     "vmmngr",
+     NULL},
+
+    {"jitter",
+     (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter,
+     "jitter",
+     NULL},
+
+#define JITCORE_PPC_REG_EXPAND(_name, _size)				\
+    { #_name, (getter) JitCpu_get_ ## _name ,				\
+	(setter) JitCpu_set_ ## _name , #_name , NULL},
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+    {NULL}  /* Sentinel */
+};
+
+
+static PyTypeObject JitCpuType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "JitCore_ppc.JitCpu",      /*tp_name*/
+    sizeof(JitCpu),            /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)JitCpu_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "JitCpu objects",          /* tp_doc */
+    0,			       /* tp_traverse */
+    0,			       /* tp_clear */
+    0,			       /* tp_richcompare */
+    0,			       /* tp_weaklistoffset */
+    0,			       /* tp_iter */
+    0,			       /* tp_iternext */
+    JitCpu_methods,            /* tp_methods */
+    JitCpu_members,            /* tp_members */
+    JitCpu_getseters,          /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)JitCpu_init,     /* tp_init */
+    0,                         /* tp_alloc */
+    JitCpu_new,                /* tp_new */
+};
+
+
+
+static PyMethodDef JitCore_ppc_Methods[] = {
+    {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS},
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+
+static PyObject *JitCore_ppc32_Error;
+
+PyMODINIT_FUNC
+initJitCore_ppc32(void)
+{
+    PyObject *m;
+
+    if (PyType_Ready(&JitCpuType) < 0)
+	return;
+
+    m = Py_InitModule("JitCore_ppc32", JitCore_ppc_Methods);
+    if (m == NULL)
+	return;
+
+    JitCore_ppc32_Error = PyErr_NewException("JitCore_ppc32.error", NULL, NULL);
+    Py_INCREF(JitCore_ppc32_Error);
+    PyModule_AddObject(m, "error", JitCore_ppc32_Error);
+
+    Py_INCREF(&JitCpuType);
+    PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType);
+
+}
+
diff --git a/miasm2/jitter/arch/JitCore_ppc32.h b/miasm2/jitter/arch/JitCore_ppc32.h
new file mode 100644
index 00000000..18cee358
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_ppc32.h
@@ -0,0 +1,24 @@
+/*
+ * _size can't be used yet because all register accesses are homogeneously
+ * 32-bit
+ */
+struct vm_cpu {
+#define JITCORE_PPC_REG_EXPAND(_name, _size)				\
+    uint32_t _name;
+#include "JitCore_ppc32_regs.h"
+#undef JITCORE_PPC_REG_EXPAND
+
+    uint64_t exception_flags;
+    uint32_t spr_access;
+    uint32_t reserve;
+    uint32_t reserve_address;
+};
+
+int32_t idiv32(struct vm_cpu *, int32_t, int32_t);
+uint32_t udiv32(struct vm_cpu *, uint32_t, uint32_t);
+int32_t imod32(struct vm_cpu *, int32_t, int32_t);
+uint32_t umod32(struct vm_cpu *, uint32_t, uint32_t);
+
+void dump_gpregs(struct vm_cpu *);
+
+typedef struct vm_cpu vm_cpu_t;
diff --git a/miasm2/jitter/arch/JitCore_ppc32_regs.h b/miasm2/jitter/arch/JitCore_ppc32_regs.h
new file mode 100644
index 00000000..d15b5e51
--- /dev/null
+++ b/miasm2/jitter/arch/JitCore_ppc32_regs.h
@@ -0,0 +1,89 @@
+JITCORE_PPC_REG_EXPAND(R0, 32)
+JITCORE_PPC_REG_EXPAND(R1, 32)
+JITCORE_PPC_REG_EXPAND(R2, 32)
+JITCORE_PPC_REG_EXPAND(R3, 32)
+JITCORE_PPC_REG_EXPAND(R4, 32)
+JITCORE_PPC_REG_EXPAND(R5, 32)
+JITCORE_PPC_REG_EXPAND(R6, 32)
+JITCORE_PPC_REG_EXPAND(R7, 32)
+JITCORE_PPC_REG_EXPAND(R8, 32)
+JITCORE_PPC_REG_EXPAND(R9, 32)
+JITCORE_PPC_REG_EXPAND(R10, 32)
+JITCORE_PPC_REG_EXPAND(R11, 32)
+JITCORE_PPC_REG_EXPAND(R12, 32)
+JITCORE_PPC_REG_EXPAND(R13, 32)
+JITCORE_PPC_REG_EXPAND(R14, 32)
+JITCORE_PPC_REG_EXPAND(R15, 32)
+JITCORE_PPC_REG_EXPAND(R16, 32)
+JITCORE_PPC_REG_EXPAND(R17, 32)
+JITCORE_PPC_REG_EXPAND(R18, 32)
+JITCORE_PPC_REG_EXPAND(R19, 32)
+JITCORE_PPC_REG_EXPAND(R20, 32)
+JITCORE_PPC_REG_EXPAND(R21, 32)
+JITCORE_PPC_REG_EXPAND(R22, 32)
+JITCORE_PPC_REG_EXPAND(R23, 32)
+JITCORE_PPC_REG_EXPAND(R24, 32)
+JITCORE_PPC_REG_EXPAND(R25, 32)
+JITCORE_PPC_REG_EXPAND(R26, 32)
+JITCORE_PPC_REG_EXPAND(R27, 32)
+JITCORE_PPC_REG_EXPAND(R28, 32)
+JITCORE_PPC_REG_EXPAND(R29, 32)
+JITCORE_PPC_REG_EXPAND(R30, 32)
+JITCORE_PPC_REG_EXPAND(R31, 32)
+
+JITCORE_PPC_REG_EXPAND(PC, 32)
+JITCORE_PPC_REG_EXPAND(LR, 32)
+JITCORE_PPC_REG_EXPAND(CTR, 32)
+JITCORE_PPC_REG_EXPAND(MSR, 32)
+
+JITCORE_PPC_REG_EXPAND(XER_SO, 32)
+JITCORE_PPC_REG_EXPAND(XER_OV, 32)
+JITCORE_PPC_REG_EXPAND(XER_CA, 32)
+JITCORE_PPC_REG_EXPAND(XER_BC, 32)
+
+JITCORE_PPC_REG_EXPAND(CR0_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR0_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR0_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR0_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR1_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR1_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR1_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR1_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR2_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR2_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR2_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR2_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR3_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR3_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR3_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR3_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR4_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR4_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR4_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR4_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR5_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR5_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR5_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR5_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR6_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR6_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR6_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR6_SO, 8)
+JITCORE_PPC_REG_EXPAND(CR7_LT, 8)
+JITCORE_PPC_REG_EXPAND(CR7_GT, 8)
+JITCORE_PPC_REG_EXPAND(CR7_EQ, 8)
+JITCORE_PPC_REG_EXPAND(CR7_SO, 8)
+
+JITCORE_PPC_REG_EXPAND(SPRG0, 32)
+JITCORE_PPC_REG_EXPAND(SPRG1, 32)
+JITCORE_PPC_REG_EXPAND(SPRG2, 32)
+JITCORE_PPC_REG_EXPAND(SPRG3, 32)
+JITCORE_PPC_REG_EXPAND(SRR0, 32)
+JITCORE_PPC_REG_EXPAND(SRR1, 32)
+JITCORE_PPC_REG_EXPAND(DAR, 32)
+JITCORE_PPC_REG_EXPAND(DSISR, 32)
+JITCORE_PPC_REG_EXPAND(PIR, 32)
+JITCORE_PPC_REG_EXPAND(PVR, 32)
+JITCORE_PPC_REG_EXPAND(DEC, 32)
+JITCORE_PPC_REG_EXPAND(TBL, 32)
+JITCORE_PPC_REG_EXPAND(TBU, 32)
diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py
index 8efd5626..56179c92 100644
--- a/miasm2/jitter/csts.py
+++ b/miasm2/jitter/csts.py
@@ -8,6 +8,7 @@ EXCEPT_NUM_UPDT_EIP = (1<<11)
 EXCEPT_CODE_AUTOMOD = (1 << 0)
 EXCEPT_SOFT_BP = (1 << 1)
 EXCEPT_INT_XX = (1 << 2)
+EXCEPT_SPR_ACCESS = (1 << 3)
 EXCEPT_BREAKPOINT_INTERN = (1 << 10)
 
 EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC)
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index ff7ba215..7a3acb2c 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -157,7 +157,7 @@ class ExceptionHandle():
         return (self.except_flag == to_cmp.except_flag)
 
 
-class jitter:
+class jitter(object):
 
     "Main class for JIT handling"
 
@@ -188,6 +188,8 @@ class jitter:
                 from miasm2.jitter.arch import JitCore_msp430 as jcore
             elif arch_name == "mips32":
                 from miasm2.jitter.arch import JitCore_mips32 as jcore
+            elif arch_name == "ppc32":
+                from miasm2.jitter.arch import JitCore_ppc32 as jcore
             else:
                 raise ValueError("unknown jit arch: %s" % arch_name)
         except ImportError:
diff --git a/setup.py b/setup.py
index 03999108..e6851364 100755
--- a/setup.py
+++ b/setup.py
@@ -14,6 +14,7 @@ def buil_all():
               'miasm2/arch/msp430',
               'miasm2/arch/sh4',
               'miasm2/arch/mips32',
+              'miasm2/arch/ppc',
               'miasm2/core',
               'miasm2/expression',
               'miasm2/ir',
@@ -48,6 +49,12 @@ def buil_all():
                   ["miasm2/jitter/JitCore.c",
                    "miasm2/jitter/vm_mngr.c",
                    "miasm2/jitter/arch/JitCore_mips32.c"]),
+        Extension("miasm2.jitter.arch.JitCore_ppc32",
+                  ["miasm2/jitter/JitCore.c",
+                   "miasm2/jitter/vm_mngr.c",
+                   "miasm2/jitter/arch/JitCore_ppc32.c"],
+                  depends=["miasm2/jitter/arch/JitCore_ppc32.h",
+                           "miasm2/jitter/arch/JitCore_ppc32_regs.h"]),
         Extension("miasm2.jitter.Jitgcc",
                   ["miasm2/jitter/Jitgcc.c"]),
         Extension("miasm2.jitter.Jitllvm",
@@ -78,6 +85,12 @@ def buil_all():
                   ["miasm2/jitter/JitCore.c",
                    "miasm2/jitter/vm_mngr.c",
                    "miasm2/jitter/arch/JitCore_mips32.c"]),
+        Extension("miasm2.jitter.arch.JitCore_ppc32",
+                  ["miasm2/jitter/JitCore.c",
+                   "miasm2/jitter/vm_mngr.c",
+                   "miasm2/jitter/arch/JitCore_ppc32.c"],
+                  depends=["miasm2/jitter/arch/JitCore_ppc32.h",
+                           "miasm2/jitter/arch/JitCore_ppc32_regs.h"]),
         Extension("miasm2.jitter.Jitllvm",
                   ["miasm2/jitter/Jitllvm.c"]),
         Extension("miasm2.jitter.Jitgcc",