about summary refs log tree commit diff stats
path: root/miasm2/arch/msp430
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miasm2/arch/msp430/__init__.py1
-rw-r--r--miasm2/arch/msp430/arch.py601
-rw-r--r--miasm2/arch/msp430/disasm.py8
-rw-r--r--miasm2/arch/msp430/ira.py75
-rw-r--r--miasm2/arch/msp430/regs.py105
-rw-r--r--miasm2/arch/msp430/sem.py440
6 files changed, 1230 insertions, 0 deletions
diff --git a/miasm2/arch/msp430/__init__.py b/miasm2/arch/msp430/__init__.py
new file mode 100644
index 00000000..bbad893b
--- /dev/null
+++ b/miasm2/arch/msp430/__init__.py
@@ -0,0 +1 @@
+__all__ = ["arch", "disasm", "regs", "sem"]
diff --git a/miasm2/arch/msp430/arch.py b/miasm2/arch/msp430/arch.py
new file mode 100644
index 00000000..74cce9ea
--- /dev/null
+++ b/miasm2/arch/msp430/arch.py
@@ -0,0 +1,601 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+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
+import regs as regs_module
+from regs import *
+
+log = logging.getLogger("armdis")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.DEBUG)
+
+
+def deref2expr_nooff(s, l, t):
+    t = t[0]
+    if len(t) == 1 and isinstance(t[0], ExprId):
+        return ExprMem(t[0], 16)
+    elif len(t) == 1 and isinstance(t[0], ExprInt):
+        return ExprMem(t[0], 16)
+    raise NotImplementedError('not fully functional')
+
+
+def deref2expr_pinc(s, l, t):
+    t = t[0]
+    if len(t) == 1 and isinstance(t[0], ExprId):
+        return ExprOp('autoinc', t[0])
+    raise NotImplementedError('not fully functional')
+
+
+def deref2expr_off(s, l, t):
+    t = t[0]
+    if len(t) == 2 and isinstance(t[1], ExprId):
+        return ExprMem(t[1] + t[0], 16)
+    raise NotImplementedError('not fully functional')
+
+
+def deref_expr(s, l, t):
+    t = t[0]
+    assert(len(t) == 1)
+    t = t[0]
+    if isinstance(t, ExprId):
+        return t
+    elif isinstance(t, ExprInt):
+        return t
+    elif isinstance(t, ExprMem):
+        return t
+    elif isinstance(t, ExprOp) and t.op == "autoinc":
+        return t
+    raise NotImplementedError('not fully functional')
+    if t[-1] == '!':
+        return ExprOp('wback', *t[:-1])
+    return t[0]
+
+
+def f_reg2expr(t):
+    t = t[0]
+    i = regs16_str.index(t)
+    r = regs16_expr[i]
+    return r
+
+# gpregs.parser.setParseAction(f_reg2expr)
+
+ARO = Suppress("@")
+LPARENT = Suppress("(")
+RPARENT = Suppress(")")
+
+PINC = Suppress("+")
+
+
+def ast_id2expr(t):
+    if not t in mn_msp430.regs.all_regs_ids_byname:
+        r = ExprId(t, 16)
+    else:
+        r = mn_msp430.regs.all_regs_ids_byname[t]
+    return r
+
+
+def ast_int2expr(a):
+    return ExprInt16(a)
+
+
+variable, operand, base_expr = gen_base_expr()
+
+my_var_parser = parse_ast(ast_id2expr, ast_int2expr)
+base_expr.setParseAction(my_var_parser)
+
+
+deref_nooff = Group(ARO + base_expr).setParseAction(deref2expr_nooff)
+deref_pinc = Group(ARO + base_expr + PINC).setParseAction(deref2expr_pinc)
+deref_off = Group(base_expr + LPARENT +
+                  gpregs.parser + RPARENT).setParseAction(deref2expr_off)
+
+
+sreg_p = Group(deref_pinc | deref_nooff |
+               deref_off | base_expr).setParseAction(deref_expr)
+
+
+class additional_info:
+
+    def __init__(self):
+        self.except_on_instr = False
+
+
+class instruction_msp430(instruction):
+    delayslot = 0
+
+    def dstflow(self):
+        if self.name.startswith('j'):
+            return True
+        return self.name in ['call']
+
+    def dstflow2label(self, symbol_pool):
+        e = self.args[0]
+        if not isinstance(e, ExprInt):
+            return
+        if self.name == "call":
+            ad = e.arg
+        else:
+            ad = e.arg + int(self.offset) + self.l
+
+        l = symbol_pool.getby_offset_create(ad)
+        s = ExprId(l, e.size)
+        self.args[0] = s
+
+    def breakflow(self):
+        if self.name.startswith('j'):
+            return True
+        if self.name.startswith('ret'):
+            return True
+        if self.name.startswith('int'):
+            return True
+        if self.name.startswith('mov') and self.args[1] == PC:
+            return True
+        return self.name in ['call']
+
+    def splitflow(self):
+        if self.name.startswith('jmp'):
+            return False
+        if self.name.startswith('j'):
+            return True
+        return self.name in ['call']
+
+    def setdstflow(self, a):
+        return
+
+    def is_subcall(self):
+        return self.name in ['call']
+
+    def getdstflow(self, symbol_pool):
+        return [self.args[0]]
+
+    def get_symbol_size(self, symbol, symbol_pool):
+        return self.mode
+
+    def fixDstOffset(self):
+        e = self.args[0]
+        if self.offset is None:
+            raise ValueError('symbol not resolved %s' % l)
+        if not isinstance(e, ExprInt):
+            # raise ValueError('dst must be int or label')
+            log.warning('dynamic dst %r' % e)
+            return
+        # return ExprInt32(e.arg - (self.offset + self.l))
+        self.args[0] = ExprInt_fromsize(self.mode, e.arg)
+
+    def get_info(self, c):
+        pass
+
+    def __str__(self):
+        o = super(instruction_msp430, self).__str__()
+        return o
+
+    def get_args_expr(self):
+        args = []
+        for a in self.args:
+            # a = a.replace_expr(replace_regs[self.mode])
+            args.append(a)
+        return args
+
+
+mode_msp430 = None
+
+
+class mn_msp430(cls_mn):
+    name = "msp430"
+    regs = regs_module
+    all_mn = []
+    bintree = {}
+    num = 0
+    delayslot = 0
+    pc = {None: PC}
+    sp = {None: SP}
+    all_mn_mode = defaultdict(list)
+    all_mn_name = defaultdict(list)
+    all_mn_inst = defaultdict(list)
+    instruction = instruction_msp430
+    max_instruction_len = 8
+
+    @classmethod
+    def getpc(cls, attrib):
+        return PC
+
+    @classmethod
+    def getsp(cls, attrib):
+        return SP
+
+    @classmethod
+    def check_mnemo(cls, fields):
+        l = sum([x.l for x in fields])
+        assert l % 16 == 00, "len %r" % l
+
+    @classmethod
+    def getbits(cls, bs, start, n):
+        if not n:
+            return 0
+        o = 0
+        if n > bs.getlen() * 8:
+            raise ValueError('not enought bits %r %r' % (n, len(bs.bin) * 8))
+        while n:
+            i = start / 8
+            c = cls.getbytes(bs, i)
+            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 getbytes(cls, bs, offset, l=1):
+        out = ""
+        for _ in xrange(l):
+            n_offset = (offset & ~1) + 1 - offset % 2
+            out += bs.getbytes(n_offset, 1)
+            offset += 1
+        return out
+
+    def decoded2bytes(self, result):
+        tmp = super(mn_msp430, self).decoded2bytes(result)
+        out = []
+        for x in tmp:
+            o = ""
+            while x:
+                o += x[:2][::-1]
+                x = x[2:]
+            out.append(o)
+        return out
+
+    @classmethod
+    def gen_modes(cls, subcls, name, bases, dct, fields):
+        dct['mode'] = None
+        return [(subcls, name, bases, dct, fields)]
+
+    def additional_info(self):
+        info = additional_info()
+        return info
+
+    @classmethod
+    def getmn(cls, name):
+        return name.upper()
+
+    def reset_class(self):
+        super(mn_msp430, self).reset_class()
+
+    def getnextflow(self, symbol_pool):
+        raise NotImplementedError('not fully functional')
+        return self.offset + 4
+
+
+def addop(name, fields, args=None, alias=False):
+    dct = {"fields": fields}
+    dct["alias"] = alias
+    if args is not None:
+        dct['args'] = args
+    type(name, (mn_msp430,), dct)
+
+
+class bw_mn(bs_mod_name):
+    prio = 5
+    mn_mod = ['.w', '.b']
+
+
+class msp430_sreg_arg(reg_noarg, m_arg):
+    prio = default_prio + 1
+    reg_info = gpregs
+    parser = sreg_p
+
+    def decode(self, v):
+        size = 16
+        if hasattr(self.parent, 'size'):
+            size = [16, 8][self.parent.size.value]
+        v = v & self.lmask
+        e = self.reg_info.expr[v]
+        if self.parent.a_s.value == 0b00:
+            if e == R3:
+                self.expr = ExprInt_fromsize(size, 0)
+            else:
+                self.expr = e
+        elif self.parent.a_s.value == 0b01:
+            if e == SR:
+                self.expr = ExprMem(ExprInt16(self.parent.off_s.value), size)
+            elif e == R3:
+                self.expr = ExprInt_fromsize(size, 1)
+            else:
+                self.expr = ExprMem(
+                    e + ExprInt16(self.parent.off_s.value), size)
+        elif self.parent.a_s.value == 0b10:
+            if e == SR:
+                self.expr = ExprInt_fromsize(size, 4)
+            elif e == R3:
+                self.expr = ExprInt_fromsize(size, 2)
+            else:
+                self.expr = ExprMem(e, size)
+        elif self.parent.a_s.value == 0b11:
+            if e == SR:
+                self.expr = ExprInt_fromsize(size, 8)
+            elif e == R3:
+                if self.parent.size.value == 0:
+                    self.expr = ExprInt_fromsize(size, 0xffff)
+                else:
+                    self.expr = ExprInt_fromsize(size, 0xff)
+            elif e == PC:
+                self.expr = ExprInt_fromsize(size, self.parent.off_s.value)
+            else:
+                self.expr = ExprOp('autoinc', e)
+        else:
+            raise NotImplementedError(
+                "unknown value self.parent.a_s.value = " +
+                "%d" % self.parent.a_s.value)
+        return True
+
+    def encode(self):
+        e = self.expr
+        if e in self.reg_info.expr:
+            self.parent.a_s.value = 0
+            self.value = self.reg_info.expr.index(e)
+        elif isinstance(e, ExprInt):
+            v = int(e.arg)
+            if v == 0xffff and self.parent.size.value == 0:
+                self.parent.a_s.value = 0b11
+                self.value = 3
+            elif v == 0xff and self.parent.size.value == 1:
+                self.parent.a_s.value = 0b11
+                self.value = 3
+            elif v == 2:
+                self.parent.a_s.value = 0b10
+                self.value = 3
+            elif v == 1:
+                self.parent.a_s.value = 0b01
+                self.value = 3
+            elif v == 8:
+                self.parent.a_s.value = 0b11
+                self.value = 2
+            elif v == 4:
+                self.parent.a_s.value = 0b10
+                self.value = 2
+            elif v == 0:
+                self.parent.a_s.value = 0b00
+                self.value = 3
+            else:
+                self.parent.a_s.value = 0b11
+                self.value = 0
+                self.parent.off_s.value = v
+        elif isinstance(e, ExprMem):
+            if isinstance(e.arg, ExprId):
+                self.parent.a_s.value = 0b10
+                self.value = self.reg_info.expr.index(e.arg)
+            elif isinstance(e.arg, ExprInt):
+                self.parent.a_s.value = 0b01
+                self.value = self.reg_info.expr.index(SR)
+                self.parent.off_s.value = int(e.arg.arg)
+            elif isinstance(e.arg, ExprOp):
+                self.parent.a_s.value = 0b01
+                self.value = self.reg_info.expr.index(e.arg.args[0])
+                self.parent.off_s.value = int(e.arg.args[1].arg)
+            else:
+                raise NotImplementedError(
+                    'unknown instance e.arg = %s' % type(e.arg))
+        elif isinstance(e, ExprOp) and e.op == "autoinc":
+            self.parent.a_s.value = 0b11
+            self.value = self.reg_info.expr.index(e.args[0])
+        else:
+            raise NotImplementedError('unknown instance e = %s' % type(e))
+        return True
+
+    @staticmethod
+    def arg2str(e):
+        if isinstance(e, ExprId):
+            o = str(e)
+        elif isinstance(e, ExprInt):
+            o = str(e)
+        elif isinstance(e, ExprOp) and e.op == "autoinc":
+            o = "@%s+" % str(e.args[0])
+        elif isinstance(e, ExprMem):
+            if isinstance(e.arg, ExprId):
+                o = "@%s" % e.arg
+            elif isinstance(e.arg, ExprInt):
+                o = "@%s" % e.arg
+            elif isinstance(e.arg, ExprOp):
+                o = "%s(%s)" % (e.arg.args[1], e.arg.args[0])
+        else:
+            raise NotImplementedError('unknown instance e = %s' % type(e))
+        return o
+
+
+class msp430_dreg_arg(msp430_sreg_arg):
+    prio = default_prio + 1
+    reg_info = gpregs
+    parser = sreg_p
+
+    def decode(self, v):
+        if hasattr(self.parent, 'size'):
+            size = [16, 8][self.parent.size.value]
+        else:
+            size = 16
+
+        v = v & self.lmask
+        e = self.reg_info.expr[v]
+        if self.parent.a_d.value == 0:
+            self.expr = e
+        elif self.parent.a_d.value == 1:
+            if e == SR:
+                x = ExprInt16(self.parent.off_d.value)
+            else:
+                x = e + ExprInt16(self.parent.off_d.value)
+            self.expr = ExprMem(x, size)
+        else:
+            raise NotImplementedError(
+                "unknown value self.parent.a_d.value = " +
+                "%d" % self.parent.a_d.value)
+        return True
+
+    def encode(self):
+        e = self.expr
+        if e in self.reg_info.expr:
+            self.parent.a_d.value = 0
+            self.value = self.reg_info.expr.index(e)
+        elif isinstance(e, ExprMem):
+            if isinstance(e.arg, ExprId):
+                r, i = e.arg, ExprInt16(0)
+            elif isinstance(e.arg, ExprOp):
+                r, i = e.arg.args[0], e.arg.args[1]
+            elif isinstance(e.arg, ExprInt):
+                r, i = SR, e.arg
+            else:
+                raise NotImplementedError(
+                    'unknown instance e.arg = %s' % type(e.arg))
+            self.parent.a_d.value = 1
+            self.value = self.reg_info.expr.index(r)
+            self.parent.off_d.value = int(i.arg)
+        else:
+            raise NotImplementedError('unknown instance e = %s' % type(e))
+        return True
+
+    @staticmethod
+    def arg2str(e):
+        if isinstance(e, ExprId):
+            o = str(e)
+        elif isinstance(e, ExprMem):
+            if isinstance(e.arg, ExprId):
+                o = "0x0(%s)" % e.arg
+            elif isinstance(e.arg, ExprInt):
+                o = "@%s" % e.arg
+            elif isinstance(e.arg, ExprOp):
+                o = "%s(%s)" % (e.arg.args[1], e.arg.args[0])
+            else:
+                raise NotImplementedError(
+                    'unknown instance e.arg = %s' % type(e.arg))
+        else:
+            raise NotImplementedError('unknown instance e = %s' % type(e))
+        return o
+
+
+class bs_cond_off_s(bs_cond):
+
+    @classmethod
+    def flen(cls, mode, v):
+        if v['a_s'] == 0b00:
+            return None
+        elif v['a_s'] == 0b01:
+            if v['sreg'] in [3]:
+                return None
+            else:
+                return 16
+        elif v['a_s'] == 0b10:
+            return None
+        elif v['a_s'] == 0b11:
+            """
+            if v['sreg'] in [2, 3]:
+                return None
+            else:
+                return 16
+            """
+            if v['sreg'] in [0]:
+                return 16
+            else:
+                return None
+        else:
+            raise NotImplementedError("unknown value v[a_s] = %d" % v['a_s'])
+
+    def encode(self):
+        return super(bs_cond, self).encode()
+
+    def decode(self, v):
+        if self.l == 0:
+            self.value = None
+        self.value = v
+        return True
+
+
+class bs_cond_off_d(bs_cond_off_s):
+
+    @classmethod
+    def flen(cls, mode, v):
+        if v['a_d'] == 0:
+            return None
+        elif v['a_d'] == 1:
+            return 16
+        else:
+            raise NotImplementedError("unknown value v[a_d] = %d" % v['a_d'])
+
+
+class msp430_offs(imm_noarg, m_arg):
+    parser = base_expr
+
+    def int2expr(self, v):
+        if v & ~self.intmask != 0:
+            return None
+        return ExprInt_fromsize(16, v)
+
+    def decodeval(self, v):
+        return v << 1
+
+    def encodeval(self, v):
+        return v >> 1
+
+    def decode(self, v):
+        v = v & self.lmask
+        if (1 << (self.l - 1)) & v:
+            v |= ~0 ^ self.lmask
+        v = self.decodeval(v)
+        self.expr = ExprInt16(v)
+        return True
+
+    def encode(self):
+        if not isinstance(self.expr, ExprInt):
+            return False
+        v = int(self.expr.arg)
+        if (1 << (self.l - 1)) & v:
+            v = -((0xffff ^ v) + 1)
+        v = self.encodeval(v)
+        self.value = (v & 0xffff) & self.lmask
+        return True
+
+
+off_s = bs(l=16, order=-10, cls=(bs_cond_off_s,), fname = "off_s")
+off_d = bs(l=16, order=-10, cls=(bs_cond_off_d,), fname = "off_d")
+
+a_s = bs(l=2, order=-4, fname='a_s')
+a_d = bs(l=1, order=-6, fname='a_d')
+
+a_d2 = bs(l=2, order=-2, fname='a_d')
+
+sreg = bs(l=4, order=-3, cls=(msp430_sreg_arg,), fname='sreg')
+dreg = bs(l=4, order=-5, cls=(msp430_dreg_arg,), fname='dreg')
+
+bw = bw_mn(l=1, order=-10, mn_mod=['.w', '.b'], fname='size')
+
+bs_f1 = bs_name(
+    l=4, name={
+        'mov': 4, 'add': 5, 'addc': 6, 'subc': 7, 'sub': 8, 'cmp': 9,
+        'dadd': 10, 'bit': 11, 'bic': 12, 'bis': 13, 'xor': 14, 'and': 15})
+addop("f1", [bs_f1, sreg, a_d, bw, a_s, dreg, off_s, off_d])
+
+bs_f2 = bs_name(l=3, name={'rrc': 0, 'rra': 2,
+                           'push': 4})
+addop("f2_1", [bs('000100'), bs_f2, bw, a_s, sreg, off_s])
+
+
+bs_f2_nobw = bs_name(l=3, name={'swpb': 1, 'sxt': 3,
+                                'call': 5})
+addop("f2_2", [bs('000100'), bs_f2_nobw, bs('0'), a_s, sreg, off_s])
+
+
+offimm = bs(l=10, cls=(msp430_offs,), fname="offs")
+
+bs_f2_jcc = bs_name(l=3, name={'jnz': 0, 'jz': 1, 'jnc': 2, 'jc': 3, 'jn': 4,
+                               'jge': 5, 'jl': 6, 'jmp': 7})
+addop("f2_3", [bs('001'), bs_f2_jcc, offimm])
diff --git a/miasm2/arch/msp430/disasm.py b/miasm2/arch/msp430/disasm.py
new file mode 100644
index 00000000..f0138bdf
--- /dev/null
+++ b/miasm2/arch/msp430/disasm.py
@@ -0,0 +1,8 @@
+from miasm2.core.asmbloc import disasmEngine
+from arch import mn_msp430
+
+
+class dis_msp430(disasmEngine):
+
+    def __init__(self, bs=None, **kwargs):
+        super(dis_msp430, self).__init__(mn_msp430, None, bs, **kwargs)
diff --git a/miasm2/arch/msp430/ira.py b/miasm2/arch/msp430/ira.py
new file mode 100644
index 00000000..8e9a70dd
--- /dev/null
+++ b/miasm2/arch/msp430/ira.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+from miasm2.expression.expression import *
+from miasm2.ir.ir import ir, irbloc
+from miasm2.ir.analysis import ira
+from miasm2.arch.msp430.sem import ir_msp430
+from miasm2.arch.msp430.regs import *
+# from miasm2.core.graph import DiGraph
+
+
+class ir_a_msp430_base(ir_msp430, ira):
+
+    def __init__(self, symbol_pool=None):
+        ir_msp430.__init__(self, symbol_pool)
+        self.ret_reg = self.arch.regs.R15
+
+
+class ir_a_msp430(ir_a_msp430_base):
+
+    def __init__(self, symbol_pool=None):
+        ir_a_msp430_base.__init__(self, symbol_pool)
+
+    # for test XXX TODO
+    def set_dead_regs(self, b):
+        b.rw[-1][1].add(self.arch.regs.zf)
+        b.rw[-1][1].add(self.arch.regs.nf)
+        b.rw[-1][1].add(self.arch.regs.of)
+        b.rw[-1][1].add(self.arch.regs.cf)
+
+        b.rw[-1][1].add(self.arch.regs.res)
+        b.rw[-1][1].add(self.arch.regs.scg1)
+        b.rw[-1][1].add(self.arch.regs.scg0)
+        b.rw[-1][1].add(self.arch.regs.osc)
+        b.rw[-1][1].add(self.arch.regs.cpuoff)
+        b.rw[-1][1].add(self.arch.regs.gie)
+
+    def call_effects(self, ad):
+        irs = [[ExprAff(self.ret_reg, ExprOp('call_func_ret', ad, self.sp)),
+                ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)),
+                ]]
+        return irs
+
+    def post_add_bloc(self, bloc, ir_blocs):
+        ir.post_add_bloc(self, bloc, ir_blocs)
+        # flow_graph = DiGraph()
+
+        l = bloc.lines[-1]
+        if not l.is_subcall():
+            return
+
+        for irb in ir_blocs:
+            # print 'X'*40
+            # print irb
+            pc_val = None
+            for exprs in irb.irs:
+                for e in exprs:
+                    if e.dst == PC:
+                        pc_val = e.src
+            if pc_val is None:
+                continue
+
+            l = bloc.lines[-1]
+            # print str(l), 'IS CALL!'
+            lbl = bloc.get_next()
+            new_lbl = self.gen_label()
+            irs = self.call_effects(pc_val)
+            nbloc = irbloc(new_lbl, ExprId(lbl, size=self.pc.size), irs)
+            nbloc.lines = [l]
+            self.blocs[new_lbl] = nbloc
+            irb.dst = ExprId(new_lbl, size=self.pc.size)
+
+    def get_out_regs(self, b):
+        return set([self.ret_reg, self.sp])
+
diff --git a/miasm2/arch/msp430/regs.py b/miasm2/arch/msp430/regs.py
new file mode 100644
index 00000000..7a389ae1
--- /dev/null
+++ b/miasm2/arch/msp430/regs.py
@@ -0,0 +1,105 @@
+from miasm2.expression.expression import *
+from miasm2.core.cpu import reg_info
+
+
+# GP
+
+regs16_str = ["PC", "SP", "SR"] + ["R%d" % i for i in xrange(3, 16)]
+regs16_expr = [ExprId(x, 16) for x in regs16_str]
+
+
+gpregs = reg_info(regs16_str, regs16_expr)
+
+PC = regs16_expr[0]
+SP = regs16_expr[1]
+SR = regs16_expr[2]
+R3 = regs16_expr[3]
+R4 = regs16_expr[4]
+R5 = regs16_expr[5]
+R6 = regs16_expr[6]
+R7 = regs16_expr[7]
+R8 = regs16_expr[8]
+R9 = regs16_expr[9]
+R10 = regs16_expr[10]
+R11 = regs16_expr[11]
+R12 = regs16_expr[12]
+R13 = regs16_expr[13]
+R14 = regs16_expr[14]
+R15 = regs16_expr[15]
+
+PC_init = ExprId("PC_init", 16)
+SP_init = ExprId("SP_init", 16)
+SR_init = ExprId("SR_init", 16)
+R3_init = ExprId("R3_init", 16)
+R4_init = ExprId("R4_init", 16)
+R5_init = ExprId("R5_init", 16)
+R6_init = ExprId("R6_init", 16)
+R7_init = ExprId("R7_init", 16)
+R8_init = ExprId("R8_init", 16)
+R9_init = ExprId("R9_init", 16)
+R10_init = ExprId("R10_init", 16)
+R11_init = ExprId("R11_init", 16)
+R12_init = ExprId("R12_init", 16)
+R13_init = ExprId("R13_init", 16)
+R14_init = ExprId("R14_init", 16)
+R15_init = ExprId("R15_init", 16)
+
+
+reg_zf = 'zf'
+reg_nf = 'nf'
+reg_of = 'of'
+reg_cf = 'cf'
+reg_cpuoff = 'cpuoff'
+reg_gie = 'gie'
+reg_osc = 'osc'
+reg_scg0 = 'scg0'
+reg_scg1 = 'scg1'
+reg_res = 'res'
+
+zf = ExprId(reg_zf, size=1)
+nf = ExprId(reg_nf, size=1)
+of = ExprId(reg_of, size=1)
+cf = ExprId(reg_cf, size=1)
+
+cpuoff = ExprId(reg_cpuoff, size=1)
+gie = ExprId(reg_gie, size=1)
+osc = ExprId(reg_osc, size=1)
+scg0 = ExprId(reg_scg0, size=1)
+scg1 = ExprId(reg_scg1, size=1)
+res = ExprId(reg_res, size=7)
+
+
+zf_init = ExprId("zf_init", size=1)
+nf_init = ExprId("nf_init", size=1)
+of_init = ExprId("of_init", size=1)
+cf_init = ExprId("cf_init", size=1)
+
+
+cpuoff_init = ExprId("cpuoff_init", size=1)
+gie_init = ExprId("gie_init", size=1)
+osc_init = ExprId("osc_init", size=1)
+scg0_init = ExprId("scg0_init", size=1)
+scg1_init = ExprId("scg1_init", size=1)
+res_init = ExprId("res_init", size=7)
+
+
+all_regs_ids = [
+    PC, SP, SR, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15,
+    zf, nf, of, cf,
+    cpuoff, gie, osc, scg0, scg1, res,
+]
+
+all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids])
+
+all_regs_ids_init = [PC_init, SP_init, SR_init, R3_init,
+                     R4_init, R5_init, R6_init, R7_init,
+                     R8_init, R9_init, R10_init, R11_init,
+                     R12_init, R13_init, R14_init, R15_init,
+                     zf_init, nf_init, of_init, cf_init,
+                     cpuoff_init, gie_init, osc_init,
+                     scg0_init, scg1_init, res_init,
+                     ]
+
+regs_init = {}
+for i, r in enumerate(all_regs_ids):
+    regs_init[r] = all_regs_ids_init[i]
diff --git a/miasm2/arch/msp430/sem.py b/miasm2/arch/msp430/sem.py
new file mode 100644
index 00000000..6fea2c21
--- /dev/null
+++ b/miasm2/arch/msp430/sem.py
@@ -0,0 +1,440 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+from miasm2.expression.expression import *
+from miasm2.arch.msp430.regs import *
+from miasm2.arch.msp430.arch import mn_msp430
+from miasm2.ir.ir import ir
+from regs import *
+
+
+# Utils
+def hex2bcd(val):
+    "Return val as BCD"
+    try:
+        return int("%x" % val, 10)
+    except ValueError:
+        raise NotImplementedError("Not defined behaviour")
+
+
+def bcd2hex(val):
+    "Return the hex value of a BCD"
+    try:
+        return int("0x%d" % val, 16)
+    except ValueError:
+        raise NotImplementedError("Not defined behaviour")
+
+
+def reset_sr_res():
+    return [ExprAff(res, ExprInt_fromsize(7, 0))]
+
+
+def update_flag_zf(a):
+    return [ExprAff(zf, ExprCond(a, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))]
+
+
+def update_flag_nf(a):
+    return [ExprAff(nf, a.msb())]
+
+
+def update_flag_pf(a):
+    return [ExprAff(pf, ExprOp('parity', a & ExprInt_from(a, 0xFF)))]
+
+
+def update_flag_cf_inv_zf(a):
+    return [ExprAff(cf, ExprCond(a, ExprInt_from(cf, 1), ExprInt_from(cf, 0)))]
+
+
+def update_flag_zn_r(a):
+    e = []
+    e += update_flag_zf(a)
+    e += update_flag_nf(a)
+    e += reset_sr_res()
+    return e
+
+
+def update_flag_sub_cf(a, b, c):
+    return [ExprAff(cf,
+        ((((a ^ b) ^ c) ^ ((a ^ c) & (a ^ b))).msb()) ^ ExprInt1(1))]
+
+
+def update_flag_add_cf(a, b, c):
+    return [ExprAff(cf, (((a ^ b) ^ c) ^ ((a ^ c) & (~(a ^ b)))).msb())]
+
+
+def update_flag_add_of(a, b, c):
+    return [ExprAff(of, (((a ^ c) & (~(a ^ b)))).msb())]
+
+
+def update_flag_sub_of(a, b, c):
+    return [ExprAff(of, (((a ^ c) & (a ^ b))).msb())]
+
+
+def mng_autoinc(a, b, size):
+    e = []
+    if not (isinstance(a, ExprOp) and a.op == "autoinc"):
+        return e, a, b
+
+    a_r = a.args[0]
+    e.append(ExprAff(a_r, a_r + ExprInt_from(a_r, size / 8)))
+    a = ExprMem(a_r, size)
+    if isinstance(b, ExprMem) and a_r in b.arg:
+        b = ExprMem(b.arg + ExprInt16(size / 8), b.size)
+    return e, a, b
+
+# Mnemonics
+
+
+def mov_b(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 8)
+    if isinstance(b, ExprMem):
+        b = ExprMem(b.arg, 8)
+        a = a[:8]
+    else:
+        a = a[:8].zeroExtend(16)
+    e.append(ExprAff(b, a))
+    return None, e, []
+
+
+def mov_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    e.append(ExprAff(b, a))
+    if b == ir.pc:
+        dst = PC
+    else:
+        dst = None
+    return dst, e, []
+
+
+def and_b(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 8)
+    c = a[:8] & b[:8]
+    e.append(ExprAff(b, c.zeroExtend(16)))
+    e += update_flag_zn_r(c)
+    e += update_flag_cf_inv_zf(c)
+    e += [ExprAff(of, ExprInt1(0))]
+    return None, e, []
+
+
+def and_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = a & b
+    e.append(ExprAff(b, c))
+    e += update_flag_zn_r(c)
+    e += update_flag_cf_inv_zf(c)
+    e += [ExprAff(of, ExprInt1(0))]
+    return None, e, []
+
+
+def bic_b(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 8)
+    c = (a[:8] ^ ExprInt8(0xff)) & b[:8]
+    c = c.zeroExtend(b.size)
+    e.append(ExprAff(b, c))
+    return None, e, []
+
+
+def bic_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = (a ^ ExprInt16(0xffff)) & b
+    e.append(ExprAff(b, c))
+    return None, e, []
+
+
+def bis_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = a | b
+    e.append(ExprAff(b, c))
+    return None, e, []
+
+
+def bit_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = a & b
+    e += update_flag_zn_r(c)
+    e += update_flag_cf_inv_zf(c)
+    e.append(ExprAff(of, ExprInt1(0)))
+    return None, e, []
+
+"""
+def sub_b(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 8)
+    c = b - a
+    e.append(ExprAff(b, c))
+    e += update_flag_zn_r(c)
+    e += update_flag_sub_cf(b, a, c)
+    return None, e, []
+"""
+
+
+def sub_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = b - a
+    e.append(ExprAff(b, c))
+    e += update_flag_zn_r(c)
+    e += update_flag_sub_cf(b, a, c)
+    # micrcorruption
+    # e += update_flag_sub_of(a, b, c)
+    # e += update_flag_sub_of(b, a, c)
+    return None, e, []
+
+
+def add_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = b + a
+    e.append(ExprAff(b, c))
+    e += update_flag_zn_r(c)
+    e += update_flag_add_cf(a, b, c)
+    e += update_flag_add_of(a, b, c)
+    return None, e, []
+
+
+def dadd_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    # TODO: microcorruption no carryflag
+    c = ExprOp("bcdadd", b, a)  # +zeroExtend(cf, 16))
+
+    e.append(ExprAff(b, c))
+    # e += update_flag_zn_r(c)
+
+    # micrcorruption
+    e += update_flag_zf(a)
+    # e += update_flag_nf(a)
+    e += reset_sr_res()
+
+    e.append(ExprAff(cf, ExprOp("bcdadd_cf", b, a)))  # +zeroExtend(cf, 16))))
+
+    # of : undefined
+    return None, e, []
+
+
+def xor_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = b ^ a
+    e.append(ExprAff(b, c))
+    e += update_flag_zn_r(c)
+    e += update_flag_cf_inv_zf(c)
+    e.append(ExprAff(of, b.msb() & a.msb()))
+    return None, e, []
+
+
+def push_w(ir, instr, a):
+    e = []
+    e.append(ExprAff(ExprMem(SP - ExprInt16(2), 16), a))
+    e.append(ExprAff(SP, SP - ExprInt16(2)))
+    return None, e, []
+
+
+def call(ir, instr, a):
+    e, a, dummy = mng_autoinc(a, None, 16)
+    n = ExprId(ir.get_next_label(instr), 16)
+    e.append(ExprAff(ExprMem(SP - ExprInt16(2), 16), n))
+    e.append(ExprAff(SP, SP - ExprInt16(2)))
+    e.append(ExprAff(PC, a))
+    return PC, e, []
+
+
+def swpb(ir, instr, a):
+    e = []
+    x, y = a[:8], a[8:16]
+    e.append(ExprAff(a, ExprCompose([(y, 0, 8),
+                                     (x, 8, 16)])))
+    return None, e, []
+
+
+def cmp_w(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 16)
+    c = b - a
+    e += update_flag_zn_r(c)
+    e += update_flag_sub_cf(a, b, c)
+    e += update_flag_sub_of(a, b, c)
+    return None, e, []
+
+
+def cmp_b(ir, instr, a, b):
+    e, a, b = mng_autoinc(a, b, 8)
+    c = b[:8] - a[:8]
+    e += update_flag_zn_r(c)
+    e += update_flag_sub_cf(a[:8], b[:8], c)
+    e += update_flag_sub_of(a[:8], b[:8], c)
+    return None, e, []
+
+
+def jz(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(zf, a, n)))
+    return PC, e, []
+
+
+def jnz(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(zf, n, a)))
+    return PC, e, []
+
+
+def jl(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(nf ^ of, a, n)))
+    return PC, e, []
+
+
+def jc(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(cf, a, n)))
+    return PC, e, []
+
+
+def jnc(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(cf, n, a)))
+    return PC, e, []
+
+
+def jge(ir, instr, a):
+    n = ExprId(ir.get_next_label(instr), 16)
+    e = []
+    e.append(ExprAff(PC, ExprCond(nf ^ of, n, a)))
+    return PC, e, []
+
+
+def jmp(ir, instr, a):
+    e = []
+    e.append(ExprAff(PC, a))
+    return PC, e, []
+
+
+def rrc_w(ir, instr, a):
+    e = []
+    c = ExprCompose([(a[1:16], 0, 15),
+                   (cf, 15, 16)])
+    e.append(ExprAff(a, c))
+    e.append(ExprAff(cf, a[:1]))
+    # e += update_flag_zn_r(c)
+
+    # micrcorruption
+    e += update_flag_zf(a)
+    # e += update_flag_nf(a)
+    e += reset_sr_res()
+
+    e.append(ExprAff(of, ExprInt1(0)))
+    return None, e, []
+
+
+def rra_w(ir, instr, a):
+    e = []
+    c = ExprCompose([(a[1:16], 0, 15),
+                   (a[15:16], 15, 16)])
+    e.append(ExprAff(a, c))
+    # TODO: error in disasm microcorruption?
+    # e.append(ExprAff(cf, a[:1]))
+    # e += update_flag_zn_r(c)
+
+    # micrcorruption
+    e += update_flag_zf(a)
+    # e += update_flag_nf(a)
+    e += reset_sr_res()
+
+    e.append(ExprAff(of, ExprInt1(0)))
+    return None, e, []
+
+
+def sxt(ir, instr, a):
+    e = []
+    c = a[:8].signExtend(16)
+    e.append(ExprAff(a, c))
+
+    e += update_flag_zn_r(c)
+    e += update_flag_cf_inv_zf(c)
+    e.append(ExprAff(of, ExprInt1(0)))
+
+    return None, e, []
+
+mnemo_func = {
+    "mov.b": mov_b,
+    "mov.w": mov_w,
+    "and.b": and_b,
+    "and.w": and_w,
+    "bic.b": bic_b,
+    "bic.w": bic_w,
+    "bis.w": bis_w,
+    "bit.w": bit_w,
+    "sub.w": sub_w,
+    "add.w": add_w,
+    "push.w": push_w,
+    "dadd.w": dadd_w,
+    "xor.w": xor_w,
+    "call": call,
+    "swpb": swpb,
+    "cmp.w": cmp_w,
+    "cmp.b": cmp_b,
+    "jz": jz,
+    "jnz": jnz,
+    "jl": jl,
+    "jc": jc,
+    "jnc": jnc,
+    "jmp": jmp,
+    "jge": jge,
+    "rrc.w": rrc_w,
+    "rra.w": rra_w,
+    "sxt": sxt,
+}
+
+
+composed_sr = ExprCompose([
+    (cf,   0,  1),
+    (zf,   1,  2),
+    (nf,   2,  3),
+    (gie,  3,  4),
+    (cpuoff,  4,  5),
+    (osc,  5,  6),
+    (scg0, 6,  7),
+    (scg1, 7,  8),
+    (of, 8,  9),
+    (res, 9, 16),
+])
+
+
+def ComposeExprAff(dst, src):
+    e = []
+    for x, start, stop in dst.args:
+        e.append(ExprAff(x, src[start:stop]))
+    return e
+
+
+class ir_msp430(ir):
+
+    def __init__(self, symbol_pool=None):
+        ir.__init__(self, mn_msp430, None, symbol_pool)
+        self.pc = PC
+        self.sp = SP
+
+    def mod_pc(self, instr, instr_ir, extra_ir):
+        pass
+
+    def get_ir(self, instr):
+        # print instr#, args
+        args = instr.args
+        dst, instr_ir, extra_ir = mnemo_func[instr.name](self, instr, *args)
+        self.mod_sr(instr, instr_ir, extra_ir)
+
+        return dst, instr_ir, extra_ir
+
+    def mod_sr(self, instr, instr_ir, extra_ir):
+        for i, x in enumerate(instr_ir):
+            x.src = x.src.replace_expr({SR: composed_sr})
+            if x.dst != SR:
+                continue
+            xx = ComposeExprAff(composed_sr, x.src)
+            instr_ir[i:i + 1] = xx
+        for i, x in enumerate(instr_ir):
+            x = ExprAff(x.dst, x.src.replace_expr(
+                {self.pc: ExprInt16(instr.offset + instr.l)}))
+            instr_ir[i] = x
+
+        if extra_ir:
+            raise NotImplementedError('not fully functional')