diff options
Diffstat (limited to 'miasm2/arch/msp430/sem.py')
| -rw-r--r-- | miasm2/arch/msp430/sem.py | 440 |
1 files changed, 440 insertions, 0 deletions
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') |