diff options
Diffstat (limited to 'miasm2/arch/x86/sem.py')
| -rw-r--r-- | miasm2/arch/x86/sem.py | 3029 |
1 files changed, 3029 insertions, 0 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py new file mode 100644 index 00000000..4b8a357b --- /dev/null +++ b/miasm2/arch/x86/sem.py @@ -0,0 +1,3029 @@ +# +# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from miasm2.expression.expression import * +from miasm2.expression.simplifications import expr_simp +from miasm2.arch.x86.regs import * +from miasm2.arch.x86.arch import mn_x86, repeat_mn, replace_regs +from miasm2.core.asmbloc import expr_is_int_or_label +from miasm2.ir.ir import ir, irbloc +import math +import struct +from regs import * + +# interrupt with eip update after instr +EXCEPT_SOFT_BP = (1 << 1) +EXCEPT_INT_XX = (1 << 2) + +EXCEPT_BREAKPOINT_INTERN = (1 << 10) + +EXCEPT_NUM_UPDT_EIP = (1 << 11) +# interrupt with eip at instr +EXCEPT_UNK_MEM_AD = (1 << 12) +EXCEPT_THROW_SEH = (1 << 13) +EXCEPT_UNK_EIP = (1 << 14) +EXCEPT_ACCESS_VIOL = (1 << 14) +EXCEPT_INT_DIV_BY_ZERO = (1 << 16) +EXCEPT_PRIV_INSN = (1 << 17) +EXCEPT_ILLEGAL_INSN = (1 << 18) +EXCEPT_UNK_MNEMO = (1 << 19) + + +""" +http://www.emulators.com/docs/nx11_flags.htm + +CF(A+B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND NOT (A XOR B)) < 0) +CF(A-B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND (A XOR B)) < 0) + +OF(A+B) = ((A XOR D) AND NOT (A XOR B)) < 0 +OF(A-B) = ((A XOR D) AND (A XOR B)) < 0 +""" + + +float_list = [ + float_st0, + float_st1, + float_st2, + float_st3, + float_st4, + float_st5, + float_st6, + float_st7, +] + + +# XXX TODO make default check against 0 or not 0 (same eq as in C) + + +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_af(a): + return [ExprAff(af, ExprCond((a & ExprInt_from(a, 0x10)), + ExprInt_from(af, 1), ExprInt_from(af, 0)))] + + +def update_flag_znp(a): + e = [] + e += update_flag_zf(a) + e += update_flag_nf(a) + e += update_flag_pf(a) + return e + + +def update_flag_logic(a): + e = [] + e += update_flag_znp(a) + e.append(ExprAff(of, ExprInt_from(of, 0))) + e.append(ExprAff(cf, ExprInt_from(cf, 0))) + return e + + +def update_flag_arith(a): + e = [] + e += update_flag_znp(a) + return e + + +def check_ops_msb(a, b, c): + if not a or not b or not c or a != b or a != c: + raise ValueError('bad ops size %s %s %s' % (a, b, c)) + + +def arith_flag(a, b, c): + a_s, b_s, c_s = a.size, b.size, c.size + check_ops_msb(a_s, b_s, c_s) + a_s, b_s, c_s = a.msb(), b.msb(), c.msb() + return a_s, b_s, c_s + +# checked: ok for adc add because b & c before +cf + + +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()) + + +# checked: ok for sbb add because b & c before +cf +def update_flag_sub_cf(a, b, c): + return ExprAff(cf, (((a ^ b) ^ c) ^ ((a ^ c) & (a ^ b))).msb()) + + +def update_flag_sub_of(a, b, c): + return ExprAff(of, (((a ^ c) & (a ^ b))).msb()) + +# z = x+y (+cf?) + + +def update_flag_add(x, y, z): + e = [] + e.append(update_flag_add_cf(x, y, z)) + e.append(update_flag_add_of(x, y, z)) + return e + +# z = x-y (+cf?) + + +def update_flag_sub(x, y, z): + e = [] + e.append(update_flag_sub_cf(x, y, z)) + e.append(update_flag_sub_of(x, y, z)) + return e + + +def set_float_cs_eip(instr): + e = [] + # XXX TODO check float updt + e.append(ExprAff(float_eip, ExprInt_from(float_eip, instr.offset))) + e.append(ExprAff(float_cs, CS)) + return e + + +def mov(ir, instr, a, b): + if a in [ES, CS, SS, DS, FS, GS]: + b = b[:a.size] + if b in [ES, CS, SS, DS, FS, GS]: + b = b.zeroExtend(a.size) + e = [ExprAff(a, b)] + return None, e, [] + + +def xchg(ir, instr, a, b): + e = [] + e.append(ExprAff(a, b)) + e.append(ExprAff(b, a)) + return None, e, [] + + +def movzx(ir, instr, a, b): + e = [ExprAff(a, b.zeroExtend(a.size))] + return None, e, [] + + +def movsx(ir, instr, a, b): + e = [ExprAff(a, b.signExtend(a.size))] + return None, e, [] + + +def lea(ir, instr, a, b): + src = b.arg + if src.size > a.size: + src = src[:a.size] + e = [ExprAff(a, src)] + return None, e, [] + + +def add(ir, instr, a, b): + e = [] + c = a + b + e += update_flag_arith(c) + e += update_flag_af(c) + e += update_flag_add(a, b, c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def xadd(ir, instr, a, b): + e = [] + c = a + b + e += update_flag_arith(c) + e += update_flag_af(c) + e += update_flag_add(b, a, c) + e.append(ExprAff(b, a)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def adc(ir, instr, a, b): + e = [] + c = a + (b + ExprCompose([(ExprInt_fromsize(a.size - 1, 0), 1, a.size), + (cf, 0, 1)])) + e += update_flag_arith(c) + e += update_flag_af(c) + e += update_flag_add(a, b, c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def sub(ir, instr, a, b): + e = [] + c = a - b + e += update_flag_arith(c) + e += update_flag_af(c) + e += update_flag_sub(a, b, c) + e.append(ExprAff(a, c)) + return None, e, [] + +# a-(b+cf) + + +def sbb(ir, instr, a, b): + e = [] + c = a - (b + ExprCompose([(ExprInt_fromsize(a.size - 1, 0), 1, a.size), + (cf, 0, 1)])) + e += update_flag_arith(c) + e += update_flag_af(c) + e += update_flag_sub(a, b, c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def neg(ir, instr, b): + e = [] + a = ExprInt_from(b, 0) + + c = a - b + e += update_flag_arith(c) + e += update_flag_sub(a, b, c) + e += update_flag_af(c) + e.append(ExprAff(b, c)) + return None, e, [] + + +def l_not(ir, instr, b): + e = [] + c = ~b + e.append(ExprAff(b, c)) + return None, e, [] + + +def l_cmp(ir, instr, a, b): + e = [] + c = a - b + e += update_flag_arith(c) + e += update_flag_sub(a, b, c) + e += update_flag_af(c) + return None, e, [] + + +def xor(ir, instr, a, b): + e = [] + c = a ^ b + e += update_flag_logic(c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def l_or(ir, instr, a, b): + e = [] + c = a | b + e += update_flag_logic(c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def l_and(ir, instr, a, b): + e = [] + c = a & b + e += update_flag_logic(c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def l_test(ir, instr, a, b): + e = [] + c = a & b + e += update_flag_logic(c) + return None, e, [] + + +def l_rol(ir, instr, a, b): + e = [] + b = b.zeroExtend(a.size) + c = ExprOp('<<<', a, b) + + new_cf = c[:1] + e.append(ExprAff(cf, new_cf)) + # hack (only valid if b=1) + e.append(ExprAff(of, c.msb() ^ new_cf)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def l_ror(ir, instr, a, b): + e = [] + b = b.zeroExtend(a.size) + c = ExprOp('>>>', a, b) + + e.append(ExprAff(cf, c.msb())) + # hack (only valid if b=1): when count == 1: a = msb-1(dest) + e.append(ExprAff(of, (c ^ a).msb())) + e.append(ExprAff(a, c)) + return None, e, [] + + +def rcl(ir, instr, a, b): + e = [] + b = b.zeroExtend(a.size) + c = ExprOp('<<<c_rez', a, b, cf.zeroExtend(a.size)) + new_cf = ExprOp('<<<c_cf', a, b, cf.zeroExtend(a.size))[:1] + + e.append(ExprAff(cf, new_cf)) + # hack (only valid if b=1) + e.append(ExprAff(of, c.msb() ^ new_cf)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def rcr(ir, instr, a, b): + e = [] + b = b.zeroExtend(a.size) + c = ExprOp('>>>c_rez', a, b, cf.zeroExtend(a.size)) + new_cf = ExprOp('>>>c_cf', a, b, cf.zeroExtend(a.size))[:1] + + e.append(ExprAff(cf, new_cf)) + # hack (only valid if b=1) + e.append(ExprAff(of, (a ^ c).msb())) + e.append(ExprAff(a, c)) + + return None, e, [] + + +def get_shift(a, b): + # b.size must match a + b = b.zeroExtend(a.size) + if a.size == 64: + shift = b & ExprInt_from(b, 0x3f) + else: + shift = b & ExprInt_from(b, 0x1f) + shift = expr_simp(shift) + return shift + + +def sar(ir, instr, a, b): + + shifter = get_shift(a, b) + c = ExprOp('a>>', a, shifter) + + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + + new_cf = ExprOp('a>>', a, (shifter - ExprInt_from(a, 1)))[:1] + + e_do = [ + ExprAff(cf, new_cf), + ExprAff(of, ExprInt_from(of, 0)), + ExprAff(a, c) + ] + + e_do += update_flag_znp(c) + + # dont generate conditional shifter on constant + if isinstance(shifter, ExprInt): + if int(shifter.arg) != 0: + return None, e_do, [] + else: + raise NotImplementedError("TODO check me") + + return ExprCond(shifter, lbl_do, lbl_skip), + [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def shr(ir, instr, a, b): + e = [] + # TODO FIX AS SAR! + shifter = get_shift(a, b) + c = ExprOp('>>', a, shifter) + + new_cf = ExprOp('>>', a, (shifter - ExprInt_from(a, 1)))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + e.append(ExprAff(of, a.msb())) + e += update_flag_znp(c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def shrd_cl(ir, instr, a, b): + e = [] + opmode, admode = s, instr.v_admode() + shifter = mRCX[instr.mode][:8].zeroExtend(a.size) & ExprInt_from(a, 0x1f) + c = (a >> shifter) | (b << (ExprInt_from(a, a.size) - shifter)) + new_cf = (a >> (shifter - ExprInt_from(a, 1)))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + e.append(ExprAff(of, a.msb())) + e += update_flag_znp(c) + e.append(ExprAff(a, c)) + return None, e, [] + + +def shrd(ir, instr, a, b, c): + e = [] + shifter = get_shift(a, c) + + d = (a >> shifter) | (b << (ExprInt_from(a, a.size) - shifter)) + new_cf = (a >> (shifter - ExprInt_from(a, 1)))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + e.append(ExprAff(of, a.msb())) + e += update_flag_znp(d) + e.append(ExprAff(a, d)) + return None, e, [] + + +def sal(ir, instr, a, b): + e = [] + shifter = get_shift(a, b) + c = ExprOp('a<<', a, shifter) + new_cf = (a >> (ExprInt_from(a, a.size) - shifter))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + e += update_flag_znp(c) + e.append(ExprAff(of, c.msb() ^ new_cf)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def shl(ir, instr, a, b): + e = [] + shifter = get_shift(a, b) + c = a << shifter + new_cf = (a >> (ExprInt_from(a, a.size) - shifter))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + e += update_flag_znp(c) + e.append(ExprAff(of, c.msb() ^ new_cf)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def shld_cl(ir, instr, a, b): + return shld(ir, instr, a, b, ecx) + + +def shld(ir, instr, a, b, c): + e = [] + shifter = c.zeroExtend(a.size) & ExprInt_from(a, 0x1f) + c = ExprOp('|', + a << shifter, + b >> (ExprInt_from(a, a.size) - shifter) + ) + + new_cf = (a >> (ExprInt_from(a, a.size) - shifter))[:1] + e.append(ExprAff(cf, ExprCond(shifter, + new_cf, + cf) + ) + ) + # XXX todo: don't update flag if shifter is 0 + e += update_flag_znp(c) + e.append(ExprAff(of, c.msb() ^ new_cf)) + e.append(ExprAff(a, ExprCond(shifter, + c, + a))) + return None, e, [] + + +# XXX todo ### +def cmc(ir, instr): + e = [ExprAff(cf, ExprCond(cf, ExprInt_from(cf, 0), ExprInt_from(cf, 1)))] + return None, e, [] + + +def clc(ir, instr): + e = [ExprAff(cf, ExprInt_from(cf, 0))] + return None, e, [] + + +def stc(ir, instr): + e = [ExprAff(cf, ExprInt_from(cf, 1))] + return None, e, [] + + +def cld(ir, instr): + e = [ExprAff(df, ExprInt_from(df, 0))] + return None, e, [] + + +def std(ir, instr): + e = [ExprAff(df, ExprInt_from(df, 1))] + return None, e, [] + + +def cli(ir, instr): + e = [ExprAff(i_f, ExprInt_from(i_f, 0))] + return None, e, [] + + +def sti(ir, instr): + e = [ExprAff(exception_flags, ExprInt32(EXCEPT_PRIV_INSN))] + e = [] # XXX TODO HACK + return None, e, [] + + +def inc(ir, instr, a): + e = [] + b = ExprInt_from(a, 1) + c = a + b + e += update_flag_arith(c) + e += update_flag_af(c) + + e.append(update_flag_add_of(a, b, c)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def dec(ir, instr, a): + e = [] + b = ExprInt_from(a, -1) + c = a + b + e += update_flag_arith(c) + e += update_flag_af(c) + + e.append(update_flag_add_of(a, b, c)) + e.append(ExprAff(a, c)) + return None, e, [] + + +def push(ir, instr, a): + e = [] + s = instr.mode + size = instr.v_opmode() + opmode, admode = s, instr.v_admode() + # special case segment regs + if a in [ES, CS, SS, DS, FS, GS]: + pass + if not s in [16, 32, 64]: + raise ValueError('bad size stacker!') + if isinstance(a, ExprInt): + a = ExprInt_fromsize(s, a.arg) + + c = mRSP[instr.mode][:s] - ExprInt_fromsize(s, s / 8) + e.append(ExprAff(mRSP[instr.mode][:s], c)) + # we sub vopmode to stack, but mem access is arg size wide + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(ExprMem(c, a.size), a)) + return None, e, [] + + +def pop(ir, instr, a): + e = [] + s = instr.mode + size = instr.v_opmode() + opmode, admode = s, instr.v_admode() + # special case segment regs + if a in [ES, CS, SS, DS, FS, GS]: + s = admode + if not s in [16, 32, 64]: + raise ValueError('bad size stacker!') + new_esp = mRSP[instr.mode][:s] + ExprInt_fromsize(s, s / 8) + e.append(ExprAff(mRSP[instr.mode][:s], new_esp)) + # XXX FIX XXX for pop [esp] + if isinstance(a, ExprMem): + a = a.replace_expr({mRSP[instr.mode]: new_esp}) + c = mRSP[instr.mode][:s] + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(a, ExprMem(c, a.size))) + return None, e, [] + + +def sete(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(zf, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def setnz(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(zf, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def setl(ir, instr, a): + e = [] + e.append( + ExprAff(a, ExprCond(nf - of, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def setg(ir, instr, a): + e = [] + a0 = ExprInt_from(a, 0) + a1 = ExprInt_from(a, 1) + e.append(ExprAff(a, ExprCond(zf, a0, a1) & ExprCond(nf - of, a0, a1))) + return None, e, [] + + +def setge(ir, instr, a): + e = [] + e.append( + ExprAff(a, ExprCond(nf - of, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def seta(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf | zf, + ExprInt_from(a, 0), + ExprInt_from(a, 1)))) + + return None, e, [] + + +def setae(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def setb(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def setbe(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf | zf, + ExprInt_from(a, 1), + ExprInt_from(a, 0))) + ) + return None, e, [] + + +def setns(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(nf, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def sets(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(nf, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def seto(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(of, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def setp(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(pf, ExprInt_from(a, 1), ExprInt_from(a, 0)))) + return None, e, [] + + +def setnp(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(pf, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def setle(ir, instr, a): + e = [] + a0 = ExprInt_from(a, 0) + a1 = ExprInt_from(a, 1) + e.append(ExprAff(a, ExprCond(zf, a1, a0) | ExprCond(nf ^ of, a1, a0))) + return None, e, [] + + +def setna(ir, instr, a): + e = [] + a0 = ExprInt_from(a, 0) + a1 = ExprInt_from(a, 1) + e.append(ExprAff(a, ExprCond(cf, a1, a0) & ExprCond(zf, a1, a0))) + return None, e, [] + + +def setnbe(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf | zf, + ExprInt_from(a, 0), + ExprInt_from(a, 1))) + ) + return None, e, [] + + +def setno(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(of, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def setnb(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprCond(cf, ExprInt_from(a, 0), ExprInt_from(a, 1)))) + return None, e, [] + + +def setalc(ir, instr): + a = mRAX[instr.mode][0:8] + e = [] + e.append( + ExprAff(a, ExprCond(cf, ExprInt_from(a, 0xff), ExprInt_from(a, 0)))) + return None, e, [] + + +def bswap(ir, instr, a): + e = [] + if a.size == 16: + c = ExprCompose([(a[:8], 8, 16), + (a[8:16], 0, 8), + ]) + elif a.size == 32: + c = ExprCompose([(a[:8], 24, 32), + (a[8:16], 16, 24), + (a[16:24], 8, 16), + (a[24:32], 0, 8), + ]) + elif a.size == 64: + c = ExprCompose([(a[:8], 56, 64), + (a[8:16], 48, 56), + (a[16:24], 40, 48), + (a[24:32], 32, 40), + (a[32:40], 24, 32), + (a[40:48], 16, 24), + (a[48:56], 8, 16), + (a[56:64], 0, 8), + ]) + else: + raise ValueError('the size DOES matter') + e.append(ExprAff(a, c)) + return None, e, [] + + +def cmps(ir, instr, size): + lbl_cmp = ExprId(ir.gen_label(), instr.mode) + lbl_df_0 = ExprId(ir.gen_label(), instr.mode) + lbl_df_1 = ExprId(ir.gen_label(), instr.mode) + lbl_next = ExprId(ir.get_next_label(instr), instr.mode) + + s = instr.v_admode() + a = ExprMem(mRDI[instr.mode][:s], size) + b = ExprMem(mRSI[instr.mode][:s], size) + + dummy, e, extra = l_cmp(ir, instr, a, b) + + e0 = [] + e0.append(ExprAff(a.arg, a.arg + ExprInt_from(a.arg, size / 8))) + e0.append(ExprAff(b.arg, b.arg + ExprInt_from(b.arg, size / 8))) + e0 = irbloc(lbl_df_0.name, lbl_next, [e0]) + + e1 = [] + e1.append(ExprAff(a.arg, a.arg - ExprInt_from(a.arg, size / 8))) + e1.append(ExprAff(b.arg, b.arg - ExprInt_from(b.arg, size / 8))) + e1 = irbloc(lbl_df_1.name, lbl_next, [e1]) + + return ExprCond(df, lbl_df_1, lbl_df_0), e, [e0, e1] + + +def scas(ir, instr, size): + lbl_cmp = ExprId(ir.gen_label(), instr.mode) + lbl_df_0 = ExprId(ir.gen_label(), instr.mode) + lbl_df_1 = ExprId(ir.gen_label(), instr.mode) + lbl_next = ExprId(ir.get_next_label(instr), instr.mode) + + s = instr.v_admode() + a = ExprMem(mRDI[instr.mode][:s], size) + + dummy, e, extra = l_cmp(ir, instr, mRAX[instr.mode][:size], a) + + e0 = [] + e0.append(ExprAff(a.arg, a.arg + ExprInt_from(a.arg, size / 8))) + e0 = irbloc(lbl_df_0.name, lbl_next, [e0]) + + e1 = [] + e1.append(ExprAff(a.arg, a.arg - ExprInt_from(a.arg, size / 8))) + e1 = irbloc(lbl_df_1.name, lbl_next, [e1]) + + return ExprCond(df, lbl_df_1, lbl_df_0), e, [e0, e1] + + +def compose_eflag(s=32): + args = [] + + regs = [cf, ExprInt1(1), pf, ExprInt1( + 0), af, ExprInt1(0), zf, nf, tf, i_f, df, of] + for i in xrange(len(regs)): + args.append((regs[i], i, i + 1)) + + args.append((iopl, 12, 14)) + + if s == 32: + regs = [nt, ExprInt1(0), rf, vm, ac, vif, vip, i_d] + elif s == 16: + regs = [nt, ExprInt1(0)] + else: + raise ValueError('unk size') + for i in xrange(len(regs)): + args.append((regs[i], i + 14, i + 15)) + if s == 32: + args.append((ExprInt_fromsize(10, 0), 22, 32)) + return ExprCompose(args) + + +def pushfd(ir, instr): + return push(ir, instr, compose_eflag()) + + +def pushfw(ir, instr): + return push(ir, instr, compose_eflag(16)) + + +def popfd(ir, instr): + tmp = ExprMem(mRSP[instr.mode]) + e = [] + e.append(ExprAff(cf, ExprSlice(tmp, 0, 1))) + e.append(ExprAff(pf, ExprSlice(tmp, 2, 3))) + e.append(ExprAff(af, ExprSlice(tmp, 4, 5))) + e.append(ExprAff(zf, ExprSlice(tmp, 6, 7))) + e.append(ExprAff(nf, ExprSlice(tmp, 7, 8))) + e.append(ExprAff(tf, ExprSlice(tmp, 8, 9))) + e.append(ExprAff(i_f, ExprSlice(tmp, 9, 10))) + e.append(ExprAff(df, ExprSlice(tmp, 10, 11))) + e.append(ExprAff(of, ExprSlice(tmp, 11, 12))) + e.append(ExprAff(iopl, ExprSlice(tmp, 12, 14))) + e.append(ExprAff(nt, ExprSlice(tmp, 14, 15))) + e.append(ExprAff(rf, ExprSlice(tmp, 16, 17))) + e.append(ExprAff(vm, ExprSlice(tmp, 17, 18))) + e.append(ExprAff(ac, ExprSlice(tmp, 18, 19))) + e.append(ExprAff(vif, ExprSlice(tmp, 19, 20))) + e.append(ExprAff(vip, ExprSlice(tmp, 20, 21))) + e.append(ExprAff(i_d, ExprSlice(tmp, 21, 22))) + e.append(ExprAff(mRSP[instr.mode], mRSP[instr.mode] + ExprInt32(4))) + e.append(ExprAff(exception_flags, + ExprCond(ExprSlice(tmp, 8, 9), + ExprInt32(EXCEPT_SOFT_BP), + exception_flags + ) + ) + ) + return None, e, [] + + +def popfw(ir, instr): + tmp = ExprMem(esp) + e = [] + e.append(ExprAff(cf, ExprSlice(tmp, 0, 1))) + e.append(ExprAff(pf, ExprSlice(tmp, 2, 3))) + e.append(ExprAff(af, ExprSlice(tmp, 4, 5))) + e.append(ExprAff(zf, ExprSlice(tmp, 6, 7))) + e.append(ExprAff(nf, ExprSlice(tmp, 7, 8))) + e.append(ExprAff(tf, ExprSlice(tmp, 8, 9))) + e.append(ExprAff(i_f, ExprSlice(tmp, 9, 10))) + e.append(ExprAff(df, ExprSlice(tmp, 10, 11))) + e.append(ExprAff(of, ExprSlice(tmp, 11, 12))) + e.append(ExprAff(iopl, ExprSlice(tmp, 12, 14))) + e.append(ExprAff(nt, ExprSlice(tmp, 14, 15))) + e.append(ExprAff(esp, esp + ExprInt32(2))) + return None, e, [] + + +def pushad(ir, instr): + e = [] + s = instr.v_opmode() + opmode, admode = s, instr.v_admode() + if not s in [16, 32, 64]: + raise ValueError('bad size stacker!') + + regs = [ + mRAX[instr.mode][:s], mRCX[instr.mode][ + :s], mRDX[instr.mode][:s], mRBX[instr.mode][:s], + mRSP[instr.mode][:s], mRBP[instr.mode][:s], + mRSI[instr.mode][:s], mRDI[instr.mode][:s]] + + for i in xrange(len(regs)): + c = mRSP[instr.mode][:s] + ExprInt_fromsize(s, -(s / 8) * (i + 1)) + e.append(ExprAff(ExprMem(c, s), regs[i])) + e.append(ExprAff(mRSP[instr.mode][:s], c)) + return None, e, [] + + +def popad(ir, instr): + e = [] + s = instr.v_opmode() + opmode, admode = s, instr.v_admode() + if not s in [16, 32, 64]: + raise ValueError('bad size stacker!') + regs = [ + mRAX[instr.mode][:s], mRCX[instr.mode][ + :s], mRDX[instr.mode][:s], mRBX[instr.mode][:s], + mRSP[instr.mode][:s], mRBP[instr.mode][:s], + mRSI[instr.mode][:s], mRDI[instr.mode][:s]] + myesp = mRSP[instr.mode][:s] + regs.reverse() + for i in xrange(len(regs)): + if regs[i] == myesp: + continue + c = myesp + ExprInt_from(myesp, ((s / 8) * i)) + e.append(ExprAff(regs[i], ExprMem(c, s))) + + c = myesp + ExprInt_from(myesp, ((s / 8) * (i + 1))) + e.append(ExprAff(myesp, c)) + + return None, e, [] + + +def call(ir, instr, dst): + e = [] + # opmode, admode = instr.opmode, instr.admode + s = dst.size + meip = mRIP[instr.mode] + opmode, admode = s, instr.v_admode() + myesp = mRSP[instr.mode][:opmode] + n = ExprId(ir.get_next_label(instr), instr.mode) + + c = myesp + ExprInt_fromsize(s, (-s / 8)) + e.append(ExprAff(myesp, c)) + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(ExprMem(c, size=s), n)) + e.append(ExprAff(meip, dst.zeroExtend(instr.mode))) + if not expr_is_int_or_label(dst): + dst = meip + return dst, e, [] + + +def ret(ir, instr, a=None): + e = [] + s = instr.mode + meip = mRIP[instr.mode] + opmode, admode = instr.v_opmode(), instr.v_admode() + s = opmode + myesp = mRSP[instr.mode][:s] + + if a is None: + a = ExprInt_fromsize(s, 0) + e.append(ExprAff(myesp, (myesp + (ExprInt_fromsize(s, (s / 8)))))) + else: + a = a.zeroExtend(s) + e.append(ExprAff(myesp, (myesp + (ExprInt_fromsize(s, (s / 8)) + a)))) + c = myesp + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(meip, ExprMem(c, size=s).zeroExtend(s))) + return meip, e, [] + + +def retf(ir, instr, a=None): + e = [] + s = instr.mode + meip = mRIP[instr.mode] + opmode, admode = instr.v_opmode(), instr.v_admode() + if a is None: + a = ExprInt_fromsize(s, 0) + s = opmode + myesp = mRSP[instr.mode][:s] + + a = a.zeroExtend(s) + + e.append(ExprAff(myesp, (myesp + (ExprInt_fromsize(s, (s / 8)) + a)))) + + c = myesp + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(meip, ExprMem(c, size=s).zeroExtend(s))) + # e.append(ExprAff(meip, ExprMem(c, size = s))) + c = myesp + ExprInt_fromsize(s, (s / 8)) + if ir.do_stk_segm: + c = ExprOp('segm', SS, c) + e.append(ExprAff(CS, ExprMem(c, size=16))) + + return meip, e, [] + + +def leave(ir, instr): + opmode, admode = instr.v_opmode(), instr.v_admode() + s = opmode + myesp = mRSP[instr.mode] + + e = [] + e.append(ExprAff(mRBP[s], ExprMem(mRBP[instr.mode], size=s))) + e.append(ExprAff(myesp, + ExprInt_fromsize(instr.mode, instr.mode / 8) + mRBP[instr.mode])) + return None, e, [] + + +def enter(ir, instr, a, b): + opmode, admode = instr.v_opmode(), instr.v_admode() + s = opmode + myesp = mRSP[instr.mode][:s] + myebp = mRBP[instr.mode][:s] + + a = a.zeroExtend(s) + + e = [] + esp_tmp = myesp - ExprInt_fromsize(s, s / 8) + e.append(ExprAff(ExprMem(esp_tmp, + size=s), + myebp)) + e.append(ExprAff(myebp, esp_tmp)) + e.append(ExprAff(myesp, myesp - (a + ExprInt_fromsize(s, s / 8)))) + return None, e, [] + + +def jmp(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + e.append(ExprAff(meip, dst)) # dst.zeroExtend(instr.mode))) + if isinstance(dst, ExprMem): + dst = meip + return dst, e, [] + + +def jmpf(ir, instr, a): + e = [] + meip = mRIP[instr.mode] + assert(isinstance(a, ExprMem) and + isinstance(a.arg, ExprOp) and + a.arg.op == "segm") + segm = a.arg.args[0] + base = a.arg.args[1] + s = instr.mode + print segm, base + m1 = ExprMem(ExprOp('segm', segm, base), 16) + m2 = ExprMem(ExprOp('segm', segm, base + ExprInt_from(base, 2)), s) + + e.append(ExprAff(meip, m1)) + e.append(ExprAff(CS, m2)) + return meip, e, [] + + +def jz(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(zf, dst, n).zeroExtend(instr.mode) + e = [ExprAff(meip, dst_o)] + return dst_o, e, [] + + +def jcxz(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(mRCX[instr.mode][:16], n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jecxz(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(mRCX[instr.mode][:32], n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jrcxz(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(mRCX[instr.mode], n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jnz(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(zf, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jp(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(pf, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jnp(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(pf, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def ja(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(cf | zf, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jae(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(cf, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jb(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(cf, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jbe(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(cf | zf, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jge(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(nf - of, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jg(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(zf | (nf - of), n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jl(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(nf - of, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jle(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(zf | (nf - of), dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def js(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(nf, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jns(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(nf, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jo(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(of, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def jno(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + n = ExprId(ir.get_next_label(instr), instr.mode) + dst_o = ExprCond(of, n, dst).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + return dst_o, e, [] + + +def loop(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + s = instr.v_opmode() + opmode, admode = s, instr.v_admode() + myecx = mRCX[instr.mode][:admode] + + n = ExprId(ir.get_next_label(instr), instr.mode) + c = myecx - ExprInt_from(myecx, 1) + e.append(ExprAff(myecx, c)) + e.append(ExprAff(meip, ExprCond(c, dst, n).zeroExtend(instr.mode))) + dst_o = ExprCond(myecx, dst, n).zeroExtend(instr.mode) + return dst_o, e, [] + + +def loopne(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + s = instr.v_opmode() + opmode, admode = s, instr.v_admode() + myecx = mRCX[instr.mode][:admode] + + n = ExprId(ir.get_next_label(instr), instr.mode) + + c = ExprOp('==', + mRCX[instr.mode][:s] - ExprInt_fromsize(s, 1), + ExprInt_fromsize(s, 0)) ^ ExprInt1(1) + c &= zf ^ ExprInt1(1) + + e.append(ExprAff(myecx, myecx - ExprInt_from(myecx, 1))) + e.append(ExprAff(meip, ExprCond(c, dst, n).zeroExtend(instr.mode))) + + # for dst, ecx has been modified! + c = ExprOp('==', + mRCX[instr.mode][:s], + ExprInt_fromsize(s, 0)) ^ ExprInt1(1) + c &= zf ^ ExprInt1(1) + dst_o = ExprCond(c, dst, n).zeroExtend(instr.mode) + return dst_o, e, [] + + +def loope(ir, instr, dst): + e = [] + meip = mRIP[instr.mode] + s = instr.v_opmode() + opmode, admode = s, instr.v_admode() + myecx = mRCX[instr.mode][:admode] + + n = ExprId(ir.get_next_label(instr), instr.mode) + c = ExprOp('==', + mRCX[instr.mode][:s] - ExprInt_fromsize(s, 1), + ExprInt_fromsize(s, 0)) ^ ExprInt1(1) + c &= zf + e.append(ExprAff(myecx, myecx - ExprInt_from(myecx, 1))) + dst_o = ExprCond(c, dst, n).zeroExtend(instr.mode) + e.append(ExprAff(meip, dst_o)) + + # for dst, ecx has been modified! + c = ExprOp('==', + mRCX[instr.mode][:s], + ExprInt_fromsize(s, 0)) ^ ExprInt1(1) + c &= zf + dst_o = ExprCond(c, dst, n).zeroExtend(instr.mode) + return dst_o, e, [] + + +# XXX size to do; eflag +def div(ir, instr, a): + e = [] + s = a.size + if s == 8: + b = mRAX[instr.mode][:16] + elif s == 16: + s1, s2 = mRDX[instr.mode][:16], mRAX[instr.mode][:16] + b = ExprCompose([(s1, 0, 16), + (s1, 16, 32)]) + elif s == 32: + s1, s2 = mRDX[instr.mode][:32], mRAX[instr.mode][:32] + b = ExprCompose([(s2, 0, 32), + (s1, 32, 64)]) + elif s == 64: + s1, s2 = mRDX[instr.mode], mRAX[instr.mode] + b = ExprCompose([(s2, 0, 64), + (s1, 64, 128)]) + else: + raise ValueError('div arg not impl', a) + + c_d = ExprOp('udiv', b, a.zeroExtend(b.size)) + c_r = ExprOp('umod', b, a.zeroExtend(b.size)) + + # if 8 bit div, only ax is affected + if s == 8: + e.append(ExprAff(b, ExprCompose([(c_d[:8], 0, 8), + (c_r[:8], 8, 16)]))) + else: + e.append(ExprAff(s1, c_r[:s])) + e.append(ExprAff(s2, c_d[:s])) + return None, e, [] + +# XXX size to do; eflag + + +def idiv(ir, instr, a): + e = [] + s = a.size + + if s == 8: + b = mRAX[instr.mode][:16] + elif s == 16: + s1, s2 = mRDX[instr.mode][:16], mRAX[instr.mode][:16] + b = ExprCompose([(s1, 0, 16), + (s1, 16, 32)]) + elif s == 32: + s1, s2 = mRDX[instr.mode][:32], mRAX[instr.mode][:32] + b = ExprCompose([(s2, 0, 32), + (s1, 32, 64)]) + else: + raise ValueError('div arg not impl', a) + + c_d = ExprOp('idiv', b, a.signExtend(b.size)) + c_r = ExprOp('imod', b, a.signExtend(b.size)) + + # if 8 bit div, only ax is affected + if s == 8: + e.append(ExprAff(b, ExprCompose([(c_d[:8], 0, 8), + (c_r[:8], 8, 16)]))) + else: + e.append(ExprAff(s1, c_r[:s])) + e.append(ExprAff(s2, c_d[:s])) + return None, e, [] + +# XXX size to do; eflag + + +def mul(ir, instr, a): + e = [] + size = a.size + if a.size in [16, 32, 64]: + result = ExprOp('*', + mRAX[instr.mode][:size].zeroExtend(size * 2), + a.zeroExtend(size * 2)) + e.append(ExprAff(mRAX[instr.mode][:size], result[:size])) + e.append(ExprAff(mRDX[instr.mode][:size], result[size:size * 2])) + + elif a.size == 8: + result = ExprOp('*', + mRAX[instr.mode][:8].zeroExtend(16), + a.zeroExtend(16)) + e.append(ExprAff(mRAX[instr.mode][:16], result)) + else: + raise ValueError('unknow size') + + e.append(ExprAff(of, ExprCond(result[size:size * 2], + ExprInt1(1), + ExprInt1(0)))) + e.append(ExprAff(cf, ExprCond(result[size:size * 2], + ExprInt1(1), + ExprInt1(0)))) + + return None, e, [] + + +def imul(ir, instr, a, b=None, c=None): + e = [] + size = a.size + if b is None: + if size in [16, 32, 64]: + result = ExprOp('*', + mRAX[instr.mode][:size].signExtend(size * 2), + a.signExtend(size * 2)) + e.append(ExprAff(mRAX[instr.mode][:size], result[:size])) + e.append(ExprAff(mRDX[instr.mode][:size], result[size:size * 2])) + elif size == 8: + dst = mRAX[instr.mode][:16] + result = ExprOp('*', + mRAX[instr.mode][:8].signExtend(16), + a.signExtend(16)) + + e.append(ExprAff(dst, result)) + e.append( + ExprAff(cf, ExprCond(result - result[:size].signExtend(size * 2), + ExprInt1(1), + ExprInt1(0)))) + e.append( + ExprAff(of, ExprCond(result - result[:size].signExtend(size * 2), + ExprInt1(1), + ExprInt1(0)))) + + else: + if c is None: + c = b + b = a + result = ExprOp('*', + b.signExtend(size * 2), + c.signExtend(size * 2)) + e.append(ExprAff(a, result[:size])) + + e.append( + ExprAff(cf, ExprCond(result - result[:size].signExtend(size * 2), + ExprInt1(1), + ExprInt1(0)))) + e.append( + ExprAff(of, ExprCond(result - result[:size].signExtend(size * 2), + ExprInt1(1), + ExprInt1(0)))) + return None, e, [] + + +def cbw(ir, instr): + e = [] + tempAL = mRAX[instr.mode][:8] + tempAX = mRAX[instr.mode][:16] + e.append(ExprAff(tempAX, tempAL.signExtend(16))) + return None, e, [] + + +def cwde(ir, instr): + e = [] + tempAX = mRAX[instr.mode][:16] + tempEAX = mRAX[instr.mode][:32] + e.append(ExprAff(tempEAX, tempAX.signExtend(32))) + return None, e, [] + + +def cdqe(ir, instr): + e = [] + tempEAX = mRAX[instr.mode][:32] + tempRAX = mRAX[instr.mode][:64] + e.append(ExprAff(tempRAX, tempEAX.signExtend(64))) + return None, e, [] + + +def cwd(ir, instr): + e = [] + tempAX = mRAX[instr.mode][:16] + tempDX = mRDX[instr.mode][:16] + c = tempAX.signExtend(32) + e.append(ExprAff(tempAX, c[:16])) + e.append(ExprAff(tempDX, c[16:32])) + return None, e, [] + + +def cdq(ir, instr): + e = [] + tempEAX = mRAX[instr.mode][:32] + tempEDX = mRDX[instr.mode][:32] + c = tempEAX.signExtend(64) + e.append(ExprAff(tempEAX, c[:32])) + e.append(ExprAff(tempEDX, c[32:64])) + return None, e, [] + + +def cqo(ir, instr): + e = [] + tempRAX = mRAX[instr.mode][:64] + tempRDX = mRDX[instr.mode][:64] + c = tempEAX.signExtend(128) + e.append(ExprAff(tempRAX, c[:64])) + e.append(ExprAff(tempRDX, c[64:127])) + return None, e, [] + + +def stos(ir, instr, size): + lbl_df_0 = ExprId(ir.gen_label(), instr.mode) + lbl_df_1 = ExprId(ir.gen_label(), instr.mode) + lbl_next = ExprId(ir.get_next_label(instr), instr.mode) + + s = instr.v_admode() + + addr_o = mRDI[instr.mode][:s] + addr = addr_o + addr_p = addr + ExprInt_from(addr, size / 8) + addr_m = addr - ExprInt_from(addr, size / 8) + if ir.do_str_segm: + mss = ES + if instr.additional_info.g2.value: + raise NotImplementedError("add segm support") + addr = ExprOp('segm', mss, addr) + + b = mRAX[instr.mode][:size] + + e0 = [] + e0.append(ExprAff(addr_o, addr_p)) + e0 = irbloc(lbl_df_0.name, lbl_next, [e0]) + + e1 = [] + e1.append(ExprAff(addr_o, addr_m)) + e1 = irbloc(lbl_df_1.name, lbl_next, [e1]) + + e = [] + e.append(ExprAff(ExprMem(addr, size), b)) + + return ExprCond(df, lbl_df_1, lbl_df_0), e, [e0, e1] + + +def lods(ir, instr, size): + lbl_df_0 = ExprId(ir.gen_label(), instr.mode) + lbl_df_1 = ExprId(ir.gen_label(), instr.mode) + lbl_next = ExprId(ir.get_next_label(instr), instr.mode) + e = [] + s = instr.v_admode() + + addr_o = mRSI[instr.mode][:s] + addr = addr_o + addr_p = addr + ExprInt_from(addr, size / 8) + addr_m = addr - ExprInt_from(addr, size / 8) + if ir.do_str_segm: + mss = DS + if instr.additional_info.g2.value: + raise NotImplementedError("add segm support") + addr = ExprOp('segm', mss, addr) + + b = mRAX[instr.mode][:size] + + e0 = [] + e0.append(ExprAff(addr_o, addr_p)) + e0 = irbloc(lbl_df_0.name, lbl_next, [e0]) + + e1 = [] + e1.append(ExprAff(addr_o, addr_m)) + e1 = irbloc(lbl_df_1.name, lbl_next, [e1]) + + e = [] + e.append(ExprAff(b, ExprMem(addr, size))) + + return ExprCond(df, lbl_df_1, lbl_df_0), e, [e0, e1] + + +def movs(ir, instr, size): + lbl_df_0 = ExprId(ir.gen_label(), instr.mode) + lbl_df_1 = ExprId(ir.gen_label(), instr.mode) + lbl_next = ExprId(ir.get_next_label(instr), instr.mode) + + s = instr.v_admode() + # a = ExprMem(mRDI[instr.mode][:s], size) + # b = ExprMem(mRSI[instr.mode][:s], size) + + a = mRDI[instr.mode][:s] + b = mRSI[instr.mode][:s] + + e = [] + src = b + dst = a + if ir.do_str_segm: + if instr.additional_info.g2.value: + raise NotImplementedError("add segm support") + src = ExprOp('segm', DS, src) + dst = ExprOp('segm', ES, dst) + e.append(ExprAff(ExprMem(dst, size), ExprMem(src, size))) + + e0 = [] + e0.append(ExprAff(a, a + ExprInt_from(a, size / 8))) + e0.append(ExprAff(b, b + ExprInt_from(b, size / 8))) + e0 = irbloc(lbl_df_0.name, lbl_next, [e0]) + + e1 = [] + e1.append(ExprAff(a, a - ExprInt_from(a, size / 8))) + e1.append(ExprAff(b, b - ExprInt_from(b, size / 8))) + e1 = irbloc(lbl_df_1.name, lbl_next, [e1]) + + return ExprCond(df, lbl_df_1, lbl_df_0), e, [e0, e1] + + +def float_prev(flt): + if not flt in float_list: + return None + i = float_list.index(flt) + if i == 0: + raise ValueError('broken index') + flt = float_list[i - 1] + return flt + + +def float_pop(avoid_flt=None): + avoid_flt = float_prev(avoid_flt) + e = [] + if avoid_flt != float_st0: + e.append(ExprAff(float_st0, float_st1)) + if avoid_flt != float_st1: + e.append(ExprAff(float_st1, float_st2)) + if avoid_flt != float_st2: + e.append(ExprAff(float_st2, float_st3)) + if avoid_flt != float_st3: + e.append(ExprAff(float_st3, float_st4)) + if avoid_flt != float_st4: + e.append(ExprAff(float_st4, float_st5)) + if avoid_flt != float_st5: + e.append(ExprAff(float_st5, float_st6)) + if avoid_flt != float_st6: + e.append(ExprAff(float_st6, float_st7)) + if avoid_flt != float_st7: + e.append(ExprAff(float_st7, ExprInt_from(float_st7, 0))) + e.append( + ExprAff(float_stack_ptr, float_stack_ptr - ExprInt_fromsize(3, 1))) + return e + +# XXX TODO + + +def fcom(ir, instr, a, b): + e = [] + """ + if isinstance(a, ExprMem): + src = ExprOp('mem_%.2d_to_double'%a.size, a) + else: + src = a + """ + src = b + e.append(ExprAff(float_c0, ExprOp('fcom_c0', a, src.zeroExtend(a.size)))) + e.append(ExprAff(float_c1, ExprOp('fcom_c1', a, src.zeroExtend(a.size)))) + e.append(ExprAff(float_c2, ExprOp('fcom_c2', a, src.zeroExtend(a.size)))) + e.append(ExprAff(float_c3, ExprOp('fcom_c3', a, src.zeroExtend(a.size)))) + + e += set_float_cs_eip(instr) + return None, e, [] + + +def ficom(ir, instr, a): + e = [] + e += set_float_cs_eip(instr) + return None, e, [] + + +def fcomi(ir, instr, a): + # Invalid emulation + InvalidEmulation + + +def fcomip(ir, instr, a): + # Invalid emulation + InvalidEmulation + + +def fucomi(ir, instr, a): + # Invalid emulation + InvalidEmulation + + +def fucomip(ir, instr, a): + # Invalid emulation, only read/write analysis is valid + cond = ExprOp('fcomp', float_st0, a) + e = [] + e.append( + ExprAff(zf, ExprCond(cond, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))) + e.append( + ExprAff(pf, ExprCond(cond, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))) + e.append( + ExprAff(cf, ExprCond(cond, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))) + return None, e, [] + + +def fcomp(ir, instr, a, b): + dst, e, extra = fcom(ir, instr, a, b) + e += float_pop() + e += set_float_cs_eip(instr) + return dst, e, extra + + +def fld(ir, instr, a): + if isinstance(a, ExprMem): + src = ExprOp('mem_%.2d_to_double' % a.size, a) + else: + src = a + + e = [] + e.append(ExprAff(float_st7, float_st6)) + e.append(ExprAff(float_st6, float_st5)) + e.append(ExprAff(float_st5, float_st4)) + e.append(ExprAff(float_st4, float_st3)) + e.append(ExprAff(float_st3, float_st2)) + e.append(ExprAff(float_st2, float_st1)) + e.append(ExprAff(float_st1, float_st0)) + e.append(ExprAff(float_st0, src)) + e.append( + ExprAff(float_stack_ptr, float_stack_ptr + ExprInt_fromsize(3, 1))) + + e += set_float_cs_eip(instr) + return None, e, [] + + +def fst(ir, instr, a): + e = [] + if isinstance(a, ExprMem): + src = ExprOp('double_to_mem_%2d' % a.size, float_st0) + else: + src = float_st0 + e.append(ExprAff(a, src)) + + e += set_float_cs_eip(instr) + return None, e, [] + + +def fstp(ir, instr, a): + dst, e, extra = fst(ir, instr, a) + e += float_pop(a) + return dst, e, extra + + +def fist(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprOp('double_to_int_%d' % a.size, float_st0))) + + e += set_float_cs_eip(instr) + return None, e, [] + + +def fistp(ir, instr, a): + dst, e, extra = fist(ir, instr, a) + e += float_pop(a) + return dst, e, extra + + +def fild(ir, instr, a): + # XXXXX + src = ExprOp('int_%.2d_to_double' % a.size, a) + e = [] + e += set_float_cs_eip(instr) + dst, e_fld, extra = fld(ir, instr, src) + e += e_fld + return dst, e, extra + + +def fldz(ir, instr): + return fld(ir, instr, ExprOp('int_32_to_double', ExprInt32(0))) + + +def fld1(ir, instr): + return fld(ir, instr, ExprOp('int_32_to_double', ExprInt32(1))) + + +def fldl2e(ir, instr): + x = struct.pack('d', 1 / math.log(2)) + x = struct.unpack('Q', x)[0] + return fld(ir, instr, ExprOp('mem_64_to_double', ExprInt64(x))) + + +def fldlg2(ir, instr): + x = struct.pack('d', math.log10(2)) + x = struct.unpack('Q', x)[0] + return fld(ir, instr, ExprOp('mem_64_to_double', ExprInt64(x))) + + +def fadd(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(a, ExprOp('fadd', a, src))) + + e += set_float_cs_eip(instr) + return None, e, [] + + +def faddp(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(float_prev(a), ExprOp('fadd', a, src))) + e += set_float_cs_eip(instr) + e += float_pop(a) + return None, e, [] + + +def fninit(ir, instr): + e = [] + e += set_float_cs_eip(instr) + return None, e, [] + + +def fnstenv(ir, instr, a): + e = [] + # XXX TODO tag word, ... + status_word = ExprCompose([(ExprInt8(0), 0, 8), + (float_c0, 8, 9), + (float_c1, 9, 10), + (float_c2, 10, 11), + (float_stack_ptr, 11, 14), + (float_c3, 14, 15), + (ExprInt1(0), 15, 16), + ]) + + s = instr.mode + ad = ExprMem(a.arg, size=16) + e.append(ExprAff(ad, float_control)) + ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 1), size=16) + e.append(ExprAff(ad, status_word)) + ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 3), size=s) + e.append(ExprAff(ad, float_eip[:s])) + ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 4), size=16) + e.append(ExprAff(ad, float_cs)) + ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 5), size=s) + e.append(ExprAff(ad, float_address[:s])) + ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 6), size=16) + e.append(ExprAff(ad, float_ds)) + return None, e, [] + + +def fsub(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(a, ExprOp('fsub', a, src))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fmul(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(a, ExprOp('fmul', a, src))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fdiv(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(a, ExprOp('fdiv', a, src))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fdivr(ir, instr, a, b=None): + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(a, ExprOp('fdiv', src, a))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fdivp(ir, instr, a, b=None): + # Invalid emulation + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(float_prev(a), ExprOp('fdiv', a, src))) + e += set_float_cs_eip(instr) + e += float_pop(a) + return None, e, [] + + +def fmulp(ir, instr, a, b=None): + # Invalid emulation + if b is None: + b = a + a = float_st0 + e = [] + if isinstance(b, ExprMem): + src = ExprOp('mem_%.2d_to_double' % b.size, b) + else: + src = b + e.append(ExprAff(float_prev(a), ExprOp('fmul', a, src))) + e += set_float_cs_eip(instr) + e += float_pop(a) + return None, e, [] + + +def ftan(ir, instr, a): + e = [] + if isinstance(a, ExprMem): + src = ExprOp('mem_%.2d_to_double' % a.size, a) + else: + src = a + e.append(ExprAff(float_st0, ExprOp('ftan', src))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fxch(ir, instr, a): + e = [] + if isinstance(a, ExprMem): + src = ExprOp('mem_%.2d_to_double' % a.size, a) + else: + src = a + e.append(ExprAff(float_st0, src)) + e.append(ExprAff(src, float_st0)) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fptan(ir, instr): + e = [] + e.append(ExprAff(float_st7, float_st6)) + e.append(ExprAff(float_st6, float_st5)) + e.append(ExprAff(float_st5, float_st4)) + e.append(ExprAff(float_st4, float_st3)) + e.append(ExprAff(float_st3, float_st2)) + e.append(ExprAff(float_st2, float_st1)) + e.append(ExprAff(float_st1, ExprOp('ftan', float_st0))) + e.append(ExprAff(float_st0, ExprOp('int_32_to_double', ExprInt32(1)))) + e.append( + ExprAff(float_stack_ptr, float_stack_ptr + ExprInt_fromsize(3, 1))) + return None, e, [] + + +def frndint(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('frndint', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fsin(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('fsin', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fcos(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('fcos', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fscale(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('fscale', float_st0, float_st1))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def f2xm1(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('f2xm1', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fsqrt(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('fsqrt', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fabs(ir, instr): + e = [] + e.append(ExprAff(float_st0, ExprOp('fabs', float_st0))) + e += set_float_cs_eip(instr) + return None, e, [] + + +def fnstsw(ir, instr, dst): + args = [(ExprInt8(0), 0, 8), + (float_c0, 8, 9), + (float_c1, 9, 10), + (float_c2, 10, 11), + (float_stack_ptr, 11, 14), + (float_c3, 14, 15), + (ExprInt1(0), 15, 16)] + e = [ExprAff(dst, ExprCompose(args))] + return None, e, [] + + +def fnstcw(ir, instr, a): + e = [] + e.append(ExprAff(a, float_control)) + return None, e, [] + + +def fldcw(ir, instr, a): + e = [] + e.append(ExprAff(float_control, a)) + return None, e, [] + + +def fwait(ir, instr): + return None, [], None + + +def nop(ir, instr, a=None): + return None, [], [] + + +def hlt(ir, instr): + e = [] + except_int = EXCEPT_PRIV_INSN + e.append(ExprAff(exception_flags, ExprInt32(except_int))) + return None, e, [] + + +def rdtsc(ir, instr): + e = [] + myEAX = mRAX[instr.mode] + myEDX = mRDX[instr.mode] + e.append(ExprAff(tsc1, tsc1 + ExprInt32(1))) + e.append(ExprAff(myEAX, tsc1)) + e.append(ExprAff(myEDX, tsc2)) + return None, e, [] + + +# XXX TODO +def daa(ir, instr): + return None, [], None + + +def aam(ir, instr, a): + e = [] + tempAL = mRAX[instr.mode][0:8] + newEAX = ExprCompose([ + (tempAL % a, 0, 8), + (tempAL / a, 8, 16), + (mRAX[instr.mode][16:], 16, mRAX[instr.mode].size), + ]) + e += [ExprAff(mRAX[instr.mode], newEAX)] + e += update_flag_arith(newEAX) + return None, e, [] + + +def aad(ir, instr, a): + e = [] + tempAL = mRAX[instr.mode][0:8] + tempAH = mRAX[instr.mode][8:16] + newEAX = ExprCompose([ + ((tempAL + (tempAH * a)) & ExprInt8(0xFF), 0, 8), + (ExprInt8(0), 8, 16), + (mRAX[instr.mode][16:], + 16, mRAX[instr.mode].size), + ]) + e += [ExprAff(mRAX[instr.mode], newEAX)] + e += update_flag_arith(newEAX) + return None, e, [] + + +def aaa(ir, instr, ): + e = [] + c = (mRAX[instr.mode][:8] & ExprInt8(0xf)) - ExprInt8(9) + + c = ExprCond(c.msb(), + ExprInt1(0), + ExprInt1(1)) & \ + ExprCond(c, + ExprInt1(1), + ExprInt1(0)) + + c |= af & ExprInt1(1) + # set AL + m_al = ExprCond(c, + (mRAX[instr.mode][:8] + ExprInt8(6)) & ExprInt8(0xF), + mRAX[instr.mode][:8] & ExprInt8(0xF)) + m_ah = ExprCond(c, + mRAX[instr.mode][8:16] + ExprInt8(1), + mRAX[instr.mode][8:16]) + + e.append(ExprAff(mRAX[instr.mode], ExprCompose([ + (m_al, 0, 8), (m_ah, 8, 16), + (mRAX[instr.mode][16:], 16, mRAX[instr.mode].size)]))) + e.append(ExprAff(af, c)) + e.append(ExprAff(cf, c)) + return None, e, [] + + +def aas(ir, instr, ): + e = [] + c = (mRAX[instr.mode][:8] & ExprInt8(0xf)) - ExprInt8(9) + + c = ExprCond(c.msb(), + ExprInt1(0), + ExprInt1(1)) & \ + ExprCond(c, + ExprInt1(1), + ExprInt1(0)) + + c |= af & ExprInt1(1) + # set AL + m_al = ExprCond(c, + (mRAX[instr.mode][:8] - ExprInt8(6)) & ExprInt8(0xF), + mRAX[instr.mode][:8] & ExprInt8(0xF)) + m_ah = ExprCond(c, + mRAX[instr.mode][8:16] - ExprInt8(1), + mRAX[instr.mode][8:16]) + + e.append(ExprAff(mRAX[instr.mode], ExprCompose([ + (m_al, 0, 8), (m_ah, 8, 16), + (mRAX[instr.mode][16:], 16, mRAX[instr.mode].size)]))) + e.append(ExprAff(af, c)) + e.append(ExprAff(cf, c)) + return None, e, [] + + +def bsf(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + + e = [ExprAff(zf, ExprCond(b, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))] + + e_do = [] + e_do.append(ExprAff(a, ExprOp('bsf', b))) + return ExprCond(b, + lbl_do, lbl_skip), e, [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def bsr(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + + e = [ExprAff(zf, ExprCond(b, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))] + + e_do = [] + e_do.append(ExprAff(a, ExprOp('bsr', b))) + return ExprCond(b, + lbl_do, lbl_skip), e, [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def arpl(ir, instr, a, b): + e = [] + e.append(ExprAff(exception_flags, ExprInt32(1 << 7))) + return None, e, [] + + +def ins(ir, instr, size): + e = [] + e.append(ExprAff(exception_flags, ExprInt32(1 << 7))) + return None, e, [] + + +def sidt(ir, instr, a): + e = [] + if not isinstance(a, ExprMem) or a.size != 32: + raise ValueError('not exprmem 32bit instance!!') + b = a.arg + print "DEFAULT SIDT ADDRESS %s!!" % str(a) + e.append(ExprAff(ExprMem(b, 32), ExprInt32(0xe40007ff))) + e.append( + ExprAff(ExprMem(ExprOp("+", b, + ExprInt_from(b, 4)), 16), ExprInt16(0x8245))) + return None, e, [] + + +def sldt(ir, instr, a): + # XXX TOOD + e = [ExprAff(exception_flags, ExprInt32(EXCEPT_PRIV_INSN))] + return None, e, [] + + +def cmovz(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + + dum, e_do, extra_irs = mov(ir, instr, a, b) + return ExprCond(zf, + lbl_do, lbl_skip), [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def cmovnz(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(zf, a, b))) + return None, e, [] + + +def cmovge(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(nf ^ of, a, b))) + return None, e, [] + + +def cmovg(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(zf | (nf ^ of), a, b))) + return None, e, [] + + +def cmovl(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(nf ^ of, b, a))) + return None, e, [] + + +def cmovle(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond((nf ^ of) | zf, b, a))) + return None, e, [] + + +def cmova(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + dum, e_do, extra_irs = mov(ir, instr, a, b) + return ExprCond(cf | zf, + lbl_skip, lbl_do), [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def cmovae(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + dum, e_do, extra_irs = mov(ir, instr, a, b) + return ExprCond(cf, + lbl_skip, lbl_do), [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def cmovbe(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + dum, e_do, extra_irs = mov(ir, instr, a, b) + return ExprCond(cf | zf, + lbl_do, lbl_skip), [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def cmovb(ir, instr, a, b): + lbl_do = ExprId(ir.gen_label(), instr.mode) + lbl_skip = ExprId(ir.get_next_label(instr), instr.mode) + dum, e_do, extra_irs = mov(ir, instr, a, b) + return ExprCond(cf, + lbl_do, lbl_skip), [], [irbloc(lbl_do.name, lbl_skip, [e_do])] + + +def cmovo(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(of, b, a))) + return None, e, [] + + +def cmovno(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond(of, a, b))) + return None, e, [] + + +def cmovs(ir, instr, a, b): + e = [] + # SF is called nf in miasm + e.append(ExprAff(a, ExprCond(nf, b, a))) + return None, e, [] + + +def cmovns(ir, instr, a, b): + e = [] + # SF is called nf in miasm + e.append(ExprAff(a, ExprCond(nf, a, b))) + return None, e, [] + + +def icebp(ir, instr): + e = [] + e.append(ExprAff(exception_flags, + ExprInt32(EXCEPT_PRIV_INSN))) + return None, e, [] +# XXX + + +def l_int(ir, instr, a): + e = [] + # XXX + if a.arg in [1, 3]: + except_int = EXCEPT_SOFT_BP + else: + except_int = EXCEPT_INT_XX + e.append(ExprAff(exception_flags, + ExprInt32(except_int))) + return None, e, [] + + +def l_sysenter(ir, instr): + e = [] + e.append(ExprAff(exception_flags, + ExprInt32(EXCEPT_PRIV_INSN))) + return None, e, [] + +# XXX + + +def l_out(ir, instr, a, b): + e = [] + e.append(ExprAff(exception_flags, + ExprInt32(EXCEPT_PRIV_INSN))) + return None, e, [] + +# XXX + + +def l_outs(ir, instr, size): + e = [] + e.append(ExprAff(exception_flags, + ExprInt32(EXCEPT_PRIV_INSN))) + return None, e, [] + +# XXX actually, xlat performs al = (ds:[e]bx + ZeroExtend(al)) + + +def xlat(ir, instr): + e = [] + a = ExprCompose([(ExprInt_fromsize(24, 0), 8, 32), + (mRAX[instr.mode][0:8], 0, 8)]) + b = ExprMem(ExprOp('+', mRBX[instr.mode], a), 8) + e.append(ExprAff(mRAX[instr.mode][0:8], b)) + return None, e, [] + + +def cpuid(ir, instr): + e = [] + e.append( + ExprAff(mRAX[instr.mode], + ExprOp('cpuid', mRAX[instr.mode], ExprInt32(0)))) + e.append( + ExprAff(mRBX[instr.mode], + ExprOp('cpuid', mRAX[instr.mode], ExprInt32(1)))) + e.append( + ExprAff(mRCX[instr.mode], + ExprOp('cpuid', mRAX[instr.mode], ExprInt32(2)))) + e.append( + ExprAff(mRDX[instr.mode], + ExprOp('cpuid', mRAX[instr.mode], ExprInt32(3)))) + return None, e, [] + + +def bittest_get(a, b): + b = b.zeroExtend(a.size) + if isinstance(a, ExprMem): + off_bit = ExprOp('&', b, ExprInt_from(a, a.size - 1)) + off_byte = (b >> ExprInt_from(a, 3)) & \ + ExprOp('!', ExprInt_from(a, a.size / 8 - 1)) + + d = ExprMem(a.arg + off_byte, a.size) + # d = ExprOp('>>', mem, off_bit) + else: + off_bit = ExprOp('&', b, ExprInt_from(a, a.size - 1)) + d = a + # d = ExprOp('>>', a, off_bit) + return d, off_bit + + +def bt(ir, instr, a, b): + e = [] + b = b.zeroExtend(a.size) + d, off_bit = bittest_get(a, b) + d = d >> off_bit + e.append(ExprAff(cf, d[:1])) + return None, e, [] + + +def btc(ir, instr, a, b): + e = [] + d, off_bit = bittest_get(a, b) + e.append(ExprAff(cf, (d >> off_bit)[:1])) + + m = ExprInt_from(a, 1) << off_bit + e.append(ExprAff(d, d ^ m)) + + return None, e, [] + + +def bts(ir, instr, a, b): + e = [] + d, off_bit = bittest_get(a, b) + e.append(ExprAff(cf, (d >> off_bit)[:1])) + m = ExprInt_from(a, 1) << off_bit + e.append(ExprAff(d, d | m)) + + return None, e, [] + + +def btr(ir, instr, a, b): + e = [] + d, off_bit = bittest_get(a, b) + e.append(ExprAff(cf, (d >> off_bit)[:1])) + m = ~(ExprInt_from(a, 1) << off_bit) + e.append(ExprAff(d, d & m)) + + return None, e, [] + + +def into(ir, instr): + return None, [], None + + +def l_in(ir, instr, a, b): + e = [] + e.append(ExprAff(exception_flags, + ExprInt32(EXCEPT_PRIV_INSN))) + return None, e, [] + + +def cmpxchg(ir, instr, a, b): + e = [] + + c = mRAX[instr.mode][:a.size] + cond = c - a + e.append( + ExprAff(zf, ExprCond(cond, ExprInt_from(zf, 0), ExprInt_from(zf, 1)))) + e.append(ExprAff(a, ExprCond(cond, + b, + a) + )) + e.append(ExprAff(c, ExprCond(cond, + a, + c) + )) + return None, e, [] + + +def lds(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprMem(b.arg, size=a.size))) + e.append(ExprAff(ds, ExprMem(b.arg + ExprInt_from(a, 2), + size=16))) + return None, e, [] + + +def les(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprMem(b.arg, size=a.size))) + e.append(ExprAff(es, ExprMem(b.arg + ExprInt_from(a, 2), + size=16))) + return None, e, [] + + +def lss(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprMem(b.arg, size=a.size))) + e.append(ExprAff(ss, ExprMem(b.arg + ExprInt_from(a, 2), + size=16))) + return None, e, [] + + +def lahf(ir, instr): + e = [] + args = [] + regs = [cf, ExprInt1(1), pf, ExprInt1(0), af, ExprInt1(0), zf, nf] + for i in xrange(len(regs)): + args.append((regs[i], i, i + 1)) + e.append(ExprAff(mRAX[instr.mode][8:16], ExprCompose(args))) + return None, e, [] + + +def sahf(ir, instr): + tmp = mRAX[instr.mode][8:16] + e = [] + e.append(ExprAff(cf, tmp[0:1])) + e.append(ExprAff(pf, tmp[2:3])) + e.append(ExprAff(af, tmp[4:5])) + e.append(ExprAff(zf, tmp[6:7])) + e.append(ExprAff(nf, tmp[7:8])) + return None, e, [] + + +def lar(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprOp('access_segment', b))) + e.append(ExprAff(zf, ExprOp('access_segment_ok', b))) + return None, e, [] + + +def lsl(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprOp('load_segment_limit', b))) + e.append(ExprAff(zf, ExprOp('load_segment_limit_ok', b))) + return None, e, [] + + +def fclex(ir, instr): + # XXX TODO + return None, [], None + + +def fnclex(ir, instr): + # XXX TODO + return None, [], None + + +def l_str(ir, instr, a): + e = [] + e.append(ExprAff(a, ExprOp('load_tr_segment_selector', ExprInt32(0)))) + return None, e, [] + + +def movd(ir, instr, a, b): + e = [] + if a.size == 64: + e.append(ExprAff(a, ExprCompose([(ExprInt32(0), 32, 64), (b, 0, 32)]))) + else: + e.append(ExprAff(a, b[0:32])) + return None, e, [] + + +def xorps(ir, instr, a, b): + e = [] + if isinstance(b, ExprMem): + b = ExprMem(b.arg, a.size) + e.append(ExprAff(a, ExprOp('xorps', a, b))) + return None, e, [] + + +def movaps(ir, instr, a, b): + e = [] + if isinstance(a, ExprMem): + a = ExprMem(a.arg, b.size) + if isinstance(b, ExprMem): + b = ExprMem(b.arg, a.size) + e.append(ExprAff(a, b)) + return None, e, [] + + +def pminsw(ir, instr, a, b): + e = [] + e.append(ExprAff(a, ExprCond((a - b).msb(), a, b))) + return None, e, [] + + +def cvtsi2sd(ir, instr, a, b): + e = [] + e.append(ExprAff(a[:b.size], ExprOp('cvtsi2sd', b))) + return None, e, [] + + +def movss(ir, instr, a, b): + e = [] + e.append(ExprAff(a[:b.size], ExprOp('movss', b))) + return None, e, [] + + +def ucomiss(ir, instr, a, b): + e = [] + e.append(ExprAff(zf, ExprOp('ucomiss_zf', a[:32], b[:32]))) + e.append(ExprAff(pf, ExprOp('ucomiss_pf', a[:32], b[:32]))) + e.append(ExprAff(cf, ExprOp('ucomiss_cf', a[:32], b[:32]))) + + e.append(ExprAff(of, ExprInt1(0))) + e.append(ExprAff(af, ExprInt1(0))) + e.append(ExprAff(nf, ExprInt1(0))) + + return None, e, [] + +mnemo_func = {'mov': mov, + 'xchg': xchg, + 'movzx': movzx, + 'movsx': movsx, + 'movsxd': movsx, + 'lea': lea, + 'add': add, + 'xadd': xadd, + 'adc': adc, + 'sub': sub, + 'sbb': sbb, + 'neg': neg, + 'not': l_not, + 'cmp': l_cmp, + 'xor': xor, + 'or': l_or, + 'and': l_and, + 'test': l_test, + 'rol': l_rol, + 'ror': l_ror, + 'rcl': rcl, + 'rcr': rcr, + 'sar': sar, + 'shr': shr, + 'shrd_cl': shrd_cl, + 'sal': sal, + 'shl': shl, + 'shld_cl': shld_cl, + 'shld': shld, + 'cmc': cmc, + 'clc': clc, + 'stc': stc, + 'cld': cld, + 'std': std, + 'cli': cli, + 'sti': sti, + 'bsf': bsf, + 'bsr': bsr, + 'inc': inc, + 'dec': dec, + 'push': push, + 'pop': pop, + 'sete': sete, + 'setnz': setnz, + 'setl': setl, + 'setg': setg, + 'setge': setge, + 'seta': seta, + 'setae': setae, + 'setb': setb, + 'setbe': setbe, + 'setns': setns, + 'sets': sets, + 'seto': seto, + 'setp': setp, + 'setpe': setp, + 'setnp': setnp, + 'setpo': setnp, + 'setle': setle, + 'setng': setle, + 'setna': setna, + 'setnbe': setnbe, + 'setno': setno, + 'setnc': setnb, + 'setz': sete, + 'setne': setnz, + 'setnb': setae, + 'setnae': setb, + 'setc': setb, + 'setnge': setl, + 'setnl': setge, + 'setnle': setg, + 'setalc': setalc, + 'bswap': bswap, + 'cmpsb': lambda ir, instr: cmps(ir, instr, 8), + 'cmpsw': lambda ir, instr: cmps(ir, instr, 16), + 'cmpsd': lambda ir, instr: cmps(ir, instr, 32), + 'scasb': lambda ir, instr: scas(ir, instr, 8), + 'scasw': lambda ir, instr: scas(ir, instr, 16), + 'scasd': lambda ir, instr: scas(ir, instr, 32), + 'pushfd': pushfd, + 'pushfw': pushfw, + 'popfd': popfd, + 'popfw': popfw, + 'pushad': pushad, + 'pusha': pushad, + 'popad': popad, + 'popa': popad, + 'call': call, + 'ret': ret, + 'retf': retf, + 'leave': leave, + 'enter': enter, + 'jmp': jmp, + 'jmpf': jmpf, + 'jz': jz, + 'je': jz, + 'jcxz': jcxz, + 'jecxz': jecxz, + 'jrcxz': jrcxz, + 'jnz': jnz, + 'jp': jp, + 'jpe': jp, + 'jnp': jnp, + 'ja': ja, + 'jae': jae, + 'jb': jb, + 'jbe': jbe, + 'jg': jg, + 'jge': jge, + 'jl': jl, + 'jle': jle, + 'js': js, + 'jns': jns, + 'jo': jo, + 'jno': jno, + 'jecxz': jecxz, + 'loop': loop, + 'loopne': loopne, + 'loope': loope, + 'div': div, + 'mul': mul, + 'imul': imul, + 'idiv': idiv, + + 'cbw': cbw, + 'cwde': cwde, + 'cdqe': cdqe, + + 'cwd': cwd, + 'cdq': cdq, + 'cqo': cqo, + + 'daa': daa, + 'aam': aam, + 'aad': aad, + 'aaa': aaa, + 'aas': aas, + 'shrd': shrd, + 'stosb': lambda ir, instr: stos(ir, instr, 8), + 'stosw': lambda ir, instr: stos(ir, instr, 16), + 'stosd': lambda ir, instr: stos(ir, instr, 32), + 'stosq': lambda ir, instr: stos(ir, instr, 64), + + 'lodsb': lambda ir, instr: lods(ir, instr, 8), + 'lodsw': lambda ir, instr: lods(ir, instr, 16), + 'lodsd': lambda ir, instr: lods(ir, instr, 32), + + 'movsb': lambda ir, instr: movs(ir, instr, 8), + 'movsw': lambda ir, instr: movs(ir, instr, 16), + 'movsd': lambda ir, instr: movs(ir, instr, 32), + 'movsq': lambda ir, instr: movs(ir, instr, 64), + 'fcomp': fcomp, + 'nop': nop, + 'fnop': nop, # XXX + 'hlt': hlt, + 'rdtsc': rdtsc, + 'fst': fst, + 'fstp': fstp, + 'fist': fist, + 'fistp': fistp, + 'fld': fld, + 'fldz': fldz, + 'fld1': fld1, + 'fldl2e': fldl2e, + 'fldlg2': fldlg2, + 'fild': fild, + 'fadd': fadd, + 'fninit': fninit, + 'faddp': faddp, + 'fsub': fsub, + 'fmul': fmul, + 'fmulp': fmulp, + 'fdiv': fdiv, + 'fdivr': fdivr, + 'fdivp': fdivp, + 'fxch': fxch, + 'fptan': fptan, + 'frndint': frndint, + 'fsin': fsin, + 'fcos': fcos, + 'fscale': fscale, + 'f2xm1': f2xm1, + 'fsqrt': fsqrt, + 'fabs': fabs, + 'fnstsw': fnstsw, + 'fnstcw': fnstcw, + 'fldcw': fldcw, + 'fwait': fwait, + 'fnstenv': fnstenv, + 'sidt': sidt, + 'sldt': sldt, + 'arpl': arpl, + 'cmovz': cmovz, + 'cmove': cmovz, + 'cmovnz': cmovnz, + 'cmovge': cmovge, + 'cmovnl': cmovge, + 'cmovg': cmovg, + 'cmovl': cmovl, + 'cmova': cmova, + 'cmovae': cmovae, + 'cmovbe': cmovbe, + 'cmovb': cmovb, + 'cmovnge': cmovl, + 'cmovle': cmovle, + 'cmovng': cmovle, + 'cmovo': cmovo, + 'cmovno': cmovno, + 'cmovs': cmovs, + 'cmovns': cmovns, + 'icebp': icebp, + 'int': l_int, + 'xlat': xlat, + 'bt': bt, + 'cpuid': cpuid, + 'jo': jo, + 'fcom': fcom, + 'ficom': ficom, + 'fcomi': fcomi, + 'fcomip': fcomip, + 'fucomi': fucomi, + 'fucomip': fucomip, + 'insb': lambda ir, instr: ins(ir, instr, 8), + 'insw': lambda ir, instr: ins(ir, instr, 16), + 'insd': lambda ir, instr: ins(ir, instr, 32), + 'btc': btc, + 'bts': bts, + 'btr': btr, + 'into': into, + 'in': l_in, + 'outsb': lambda ir, instr: l_outs(ir, instr, 8), + 'outsw': lambda ir, instr: l_outs(ir, instr, 16), + 'outsd': lambda ir, instr: l_outs(ir, instr, 32), + + 'out': l_out, + "sysenter": l_sysenter, + "cmpxchg": cmpxchg, + "lds": lds, + "les": les, + "lss": lss, + "lahf": lahf, + "sahf": sahf, + "lar": lar, + "lsl": lsl, + "fclex": fclex, + "fnclex": fnclex, + "str": l_str, + "movd": movd, + "movaps": movaps, + "xorps": xorps, + + "pminsw": pminsw, + "cvtsi2sd": cvtsi2sd, + "movss": movss, + + "ucomiss": ucomiss, + } + + +class ir_x86_16(ir): + + def __init__(self, symbol_pool=None): + ir.__init__(self, mn_x86, 16, symbol_pool) + self.do_stk_segm = False + self.do_ds_segm = False + self.do_str_segm = False + self.do_all_segm = False + self.pc = IP + self.sp = SP + + def mod_pc(self, instr, instr_ir, extra_ir): + pass + + def get_ir(self, instr): + args = instr.args[:] + my_ss = None + if self.do_ds_segm: + my_ss = DS + if self.do_all_segm and instr.additional_info.g2.value: + my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ + instr.additional_info.g2.value] + if my_ss is not None: + for i, a in enumerate(args): + if isinstance(a, ExprMem) and not a.is_op_segm(): + args[i] = ExprMem(ExprOp('segm', my_ss, a.arg), a.size) + + dst, instr_ir, extra_ir = mnemo_func[ + instr.name.lower()](self, instr, *args) + self.mod_pc(instr, instr_ir, extra_ir) + + self.mod_pc(instr, instr_ir, extra_ir) + instr.additional_info.except_on_instr = False + if instr.additional_info.g1.value & 6 == 0 or \ + not instr.name in repeat_mn: + return dst, instr_ir, extra_ir + instr.additional_info.except_on_instr = True + # get instruction size + s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] + size = instr.v_opmode() + c_reg = mRCX[instr.mode][:size] + out_ir = [] + zf_val = None + # set if zf is tested (cmps, scas) + for e in instr_ir: # +[updt_c]: + if e.dst == zf: + zf_val = e.src + + # end condition + if zf_val is None: + c_cond = ExprCond(c_reg, ExprInt1(0), ExprInt1(1)) + elif instr.additional_info.g1.value & 2: # REPNE + # c_cond = ExprCond(c_reg, ExprInt1(0), ExprInt1(1)) | (zf_val) + c_cond = ExprCond(c_reg, ExprInt1(0), ExprInt1(1)) | (zf) + elif instr.additional_info.g1.value & 4: # REP + # c_cond = ExprCond(c_reg, ExprInt1(0), ExprInt1(1)) | + # (zf_val^ExprInt32(1)) + c_cond = ExprCond( + c_reg, ExprInt1(0), ExprInt1(1)) | (zf ^ ExprInt1(1)) + + # gen while + lbl_do = ExprId(self.gen_label(), instr.mode) + lbl_end = ExprId(self.gen_label(), instr.mode) + lbl_skip = ExprId(self.get_next_label(instr), instr.mode) + lbl_next = ExprId(self.get_next_label(instr), instr.mode) + + for b in extra_ir: + # print repr(b) + # print b + # self.replace_expr_in_ir(b, {lbl_next:lbl_end}) + b.dst = b.dst.replace_expr({lbl_next: lbl_end}) + # print b + + cond_bloc = [] + cond_bloc.append(ExprAff(c_reg, c_reg - ExprInt_from(c_reg, 1))) + cond_bloc = irbloc( + lbl_end.name, ExprCond(c_cond, lbl_skip, lbl_do), [cond_bloc]) + e_do = instr_ir + + c = irbloc(lbl_do.name, dst, [e_do]) + c.except_automod = False + return ExprCond(c_reg, lbl_do, lbl_skip), [], [cond_bloc, c] + extra_ir + + def expr_fix_regs_for_mode(self, e, mode=64): + return e.replace_expr(replace_regs[mode]) + + def expraff_fix_regs_for_mode(self, e, mode=64): + dst = self.expr_fix_regs_for_mode(e.dst, mode) + src = self.expr_fix_regs_for_mode(e.src, mode) + return ExprAff(dst, src) + + def irbloc_fix_regs_for_mode(self, irbloc, mode=64): + for irs in irbloc.irs: + for i, e in enumerate(irs): + """ + special case for 64 bits: + if destination is a 32 bit reg, zero extend the 64 bit reg + """ + if mode == 64: + if (isinstance(e.dst, ExprId) and e.dst.size == 32 and + e.dst in replace_regs[64]): + src = self.expr_fix_regs_for_mode(e.src, mode) + dst = replace_regs[64][e.dst].arg + e = ExprAff(dst, src.zeroExtend(64)) + irs[i] = self.expr_fix_regs_for_mode(e, mode) + irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode) + + +class ir_x86_32(ir_x86_16): + + def __init__(self, symbol_pool=None): + ir.__init__(self, mn_x86, 32, symbol_pool) + self.do_stk_segm = False + self.do_ds_segm = False + self.do_str_segm = False + self.do_all_segm = False + self.pc = EIP + self.sp = ESP + + +class ir_x86_64(ir_x86_16): + + def __init__(self, symbol_pool=None): + ir.__init__(self, mn_x86, 64, symbol_pool) + self.do_stk_segm = False + self.do_ds_segm = False + self.do_str_segm = False + self.do_all_segm = False + self.pc = RIP + self.sp = RSP + + def mod_pc(self, instr, instr_ir, extra_ir): + # fix RIP for 64 bit + for i, x in enumerate(instr_ir): + if x.dst != self.pc: + x.dst = x.dst.replace_expr( + {self.pc: ExprInt64(instr.offset + instr.l)}) + x = ExprAff(x.dst, x.src.replace_expr( + {self.pc: ExprInt64(instr.offset + instr.l)})) + instr_ir[i] = x + for b in extra_ir: + for irs in b.irs: + for i, x in enumerate(irs): + if x.dst != self.pc: + x.dst = x.dst.replace_expr( + {self.pc: ExprInt64(instr.offset + instr.l)}) + x = ExprAff(x.dst, x.src.replace_expr( + {self.pc: ExprInt64(instr.offset + instr.l)})) + irs[i] = x |