diff options
Diffstat (limited to 'miasm/arch/x86/sem.py')
| -rw-r--r-- | miasm/arch/x86/sem.py | 6065 |
1 files changed, 0 insertions, 6065 deletions
diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py deleted file mode 100644 index d19290b6..00000000 --- a/miasm/arch/x86/sem.py +++ /dev/null @@ -1,6065 +0,0 @@ -# -# 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 builtins import range - -from future.utils import viewitems - -import logging -import miasm.expression.expression as m2_expr -from miasm.expression.simplifications import expr_simp -from miasm.arch.x86.regs import * -from miasm.arch.x86.arch import mn_x86, repeat_mn, replace_regs, is_mem_segm -from miasm.ir.ir import Lifter, IRBlock, AssignBlock -from miasm.core.sembuilder import SemBuilder -from miasm.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_ILLEGAL_INSN, \ - EXCEPT_PRIV_INSN, EXCEPT_SOFT_BP, EXCEPT_INT_XX, EXCEPT_INT_1, \ - EXCEPT_SYSCALL -import math -import struct - - -LOG_X86_SEM = logging.getLogger("x86_sem") -CONSOLE_HANDLER = logging.StreamHandler() -CONSOLE_HANDLER.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -LOG_X86_SEM.addHandler(CONSOLE_HANDLER) -LOG_X86_SEM.setLevel(logging.WARNING) - - -# SemBuilder context -ctx = {'mRAX': mRAX, - 'mRBX': mRBX, - 'mRCX': mRCX, - 'mRDX': mRDX, - 'zf': zf, - } -sbuild = SemBuilder(ctx) - - - -""" -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 -""" - - -# XXX TODO make default check against 0 or not 0 (same eq as in C) -def update_flag_zf_eq(a, b): - return [m2_expr.ExprAssign(zf, m2_expr.ExprOp("FLAG_EQ_CMP", a, b))] - - -def update_flag_zf(a): - return [ - m2_expr.ExprAssign( - zf, - m2_expr.ExprCond( - a, - m2_expr.ExprInt(0, zf.size), - m2_expr.ExprInt(1, zf.size) - ) - ) - ] - - -def update_flag_nf(arg): - return [ - m2_expr.ExprAssign( - nf, - m2_expr.ExprOp("FLAG_SIGN_SUB", arg, m2_expr.ExprInt(0, arg.size)) - ) - ] - - -def update_flag_pf(a): - return [m2_expr.ExprAssign(pf, - m2_expr.ExprOp('parity', - a & m2_expr.ExprInt(0xFF, a.size)))] - - -def update_flag_af(op1, op2, res): - return [m2_expr.ExprAssign(af, (op1 ^ op2 ^ res)[4:5])] - - -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_np(result): - e = [] - e += update_flag_nf(result) - e += update_flag_pf(result) - return e - - -def null_flag_co(): - e = [] - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprInt(0, cf.size))) - return e - - -def update_flag_arith(a): - e = [] - e += update_flag_znp(a) - return e - - -def update_flag_zfaddwc_eq(arg1, arg2, arg3): - return [m2_expr.ExprAssign(zf, m2_expr.ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))] - -def update_flag_zfsubwc_eq(arg1, arg2, arg3): - return [m2_expr.ExprAssign(zf, m2_expr.ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))] - - -def update_flag_arith_add_znp(arg1, arg2): - """ - Compute znp flags for (arg1 + arg2) - """ - e = [] - e += update_flag_zf_eq(arg1, -arg2) - e += [m2_expr.ExprAssign(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, -arg2))] - e += update_flag_pf(arg1+arg2) - return e - - -def update_flag_arith_addwc_znp(arg1, arg2, arg3): - """ - Compute znp flags for (arg1 + arg2 + cf) - """ - e = [] - e += update_flag_zfaddwc_eq(arg1, arg2, arg3) - e += [m2_expr.ExprAssign(nf, m2_expr.ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))] - e += update_flag_pf(arg1+arg2+arg3.zeroExtend(arg2.size)) - return e - - - - -def update_flag_arith_sub_znp(arg1, arg2): - """ - Compute znp flags for (arg1 - arg2) - """ - e = [] - e += update_flag_zf_eq(arg1, arg2) - e += [m2_expr.ExprAssign(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, arg2))] - e += update_flag_pf(arg1 - arg2) - return e - - -def update_flag_arith_subwc_znp(arg1, arg2, arg3): - """ - Compute znp flags for (arg1 - (arg2 + cf)) - """ - e = [] - e += update_flag_zfsubwc_eq(arg1, arg2, arg3) - e += [m2_expr.ExprAssign(nf, m2_expr.ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))] - e += update_flag_pf(arg1 - (arg2+arg3.zeroExtend(arg2.size))) - 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(op1, op2, res): - "Compute cf in @res = @op1 + @op2" - #return [m2_expr.ExprAssign(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, -op2))] - return [m2_expr.ExprAssign(cf, m2_expr.ExprOp("FLAG_ADD_CF", op1, op2))] - - -def update_flag_add_of(op1, op2, res): - "Compute of in @res = @op1 + @op2" - return [m2_expr.ExprAssign(of, m2_expr.ExprOp("FLAG_ADD_OF", op1, op2))] - - -# checked: ok for sbb add because b & c before +cf -def update_flag_sub_cf(op1, op2, res): - "Compote CF in @res = @op1 - @op2" - return [m2_expr.ExprAssign(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, op2))] - - -def update_flag_sub_of(op1, op2, res): - "Compote OF in @res = @op1 - @op2" - return [m2_expr.ExprAssign(of, m2_expr.ExprOp("FLAG_SUB_OF", op1, op2))] - - -def update_flag_addwc_cf(op1, op2, op3): - "Compute cf in @res = @op1 + @op2 + @op3" - return [m2_expr.ExprAssign(cf, m2_expr.ExprOp("FLAG_ADDWC_CF", op1, op2, op3))] - - -def update_flag_addwc_of(op1, op2, op3): - "Compute of in @res = @op1 + @op2 + @op3" - return [m2_expr.ExprAssign(of, m2_expr.ExprOp("FLAG_ADDWC_OF", op1, op2, op3))] - - - -def update_flag_subwc_cf(op1, op2, op3): - "Compute cf in @res = @op1 + @op2 + @op3" - return [m2_expr.ExprAssign(cf, m2_expr.ExprOp("FLAG_SUBWC_CF", op1, op2, op3))] - - -def update_flag_subwc_of(op1, op2, op3): - "Compute of in @res = @op1 + @op2 + @op3" - return [m2_expr.ExprAssign(of, m2_expr.ExprOp("FLAG_SUBWC_OF", op1, op2, op3))] - - - - -def update_flag_arith_add_co(x, y, z): - e = [] - e += update_flag_add_cf(x, y, z) - e += update_flag_add_of(x, y, z) - return e - - -def update_flag_arith_sub_co(x, y, z): - e = [] - e += update_flag_sub_cf(x, y, z) - e += update_flag_sub_of(x, y, z) - return e - - - - -def update_flag_arith_addwc_co(arg1, arg2, arg3): - e = [] - e += update_flag_addwc_cf(arg1, arg2, arg3) - e += update_flag_addwc_of(arg1, arg2, arg3) - return e - - -def update_flag_arith_subwc_co(arg1, arg2, arg3): - e = [] - e += update_flag_subwc_cf(arg1, arg2, arg3) - e += update_flag_subwc_of(arg1, arg2, arg3) - return e - - - -def set_float_cs_eip(instr): - e = [] - # XXX TODO check float updt - e.append(m2_expr.ExprAssign(float_eip, - m2_expr.ExprInt(instr.offset, float_eip.size))) - e.append(m2_expr.ExprAssign(float_cs, CS)) - return e - - -def mode2addrsize(mode): - """Returns the address size for a given @mode""" - - mode2size = {16:32, 32:32, 64:64} - if mode not in mode2size: - raise RuntimeError("Unknown size %s", mode) - return mode2size[mode] - - -def instr2addrsize(instr): - """Returns the address size for a given @instr""" - - return mode2addrsize(instr.mode) - - -def expraddr(mode, ptr): - """Returns memory address pointer with size according to current @mode""" - return ptr.zeroExtend(mode2addrsize(mode)) - - -def fix_mem_args_size(instr, *args): - out = [] - for arg in args: - if not arg.is_mem(): - out.append(arg) - continue - ptr = arg.ptr - size = arg.size - if ptr.is_op('segm'): - ptr = m2_expr.ExprOp( - 'segm', ptr.args[0], expraddr(instr.mode, ptr.args[1])) - else: - ptr = expraddr(instr.mode, ptr) - out.append(m2_expr.ExprMem(ptr, size)) - return out - - -def mem2double(instr, arg): - """ - Add float conversion if argument is an ExprMem - @arg: argument to transform - """ - if isinstance(arg, m2_expr.ExprMem): - if arg.size > 64: - # TODO: move to 80 bits - arg = m2_expr.ExprMem(expraddr(instr.mode, arg.ptr), size=64) - return m2_expr.ExprOp('sint_to_fp', arg.signExtend(64)) - else: - return arg - - -def float_implicit_st0(arg1, arg2): - """ - Generate full float operators if one argument is implicit (float_st0) - """ - if arg2 is None: - arg2 = arg1 - arg1 = float_st0 - return arg1, arg2 - - -def gen_jcc(ir, instr, cond, dst, jmp_if): - """ - Macro to generate jcc semantic - @ir: ir instance - @instr: instruction - @cond: condition of the jcc - @dst: the destination if jcc is taken - @jmp_if: jump if/notif cond - """ - - e = [] - meip = mRIP[ir.IRDst.size] - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, dst.size) - - if jmp_if: - dstA, dstB = dst, loc_next_expr - else: - dstA, dstB = loc_next_expr, dst - mn_dst = m2_expr.ExprCond(cond, - dstA.zeroExtend(ir.IRDst.size), - dstB.zeroExtend(ir.IRDst.size)) - e.append(m2_expr.ExprAssign(meip, mn_dst)) - e.append(m2_expr.ExprAssign(ir.IRDst, mn_dst)) - return e, [] - - -def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if): - """Generate fcmov - @ir: ir instance - @instr: instruction instance - @cond: condition - @mov_if: invert condition if False""" - - loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_skip = ir.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) - if mov_if: - dstA, dstB = loc_do_expr, loc_skip_expr - else: - dstA, dstB = loc_skip_expr, loc_do_expr - e = [] - e_do, extra_irs = [m2_expr.ExprAssign(arg1, arg2)], [] - e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) - e.append(m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) - return e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])] - - -def gen_cmov(ir, instr, cond, dst, src, mov_if): - """Generate cmov - @ir: ir instance - @instr: instruction instance - @cond: condition - @mov_if: invert condition if False""" - - loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_skip = ir.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) - if mov_if: - dstA, dstB = loc_do_expr, loc_skip_expr - else: - dstA, dstB = loc_skip_expr, loc_do_expr - e = [] - if instr.mode == 64: - # Force destination set in order to zero high bit orders - # In 64 bit: - # cmovz eax, ebx - # if zf == 0 => high part of RAX is set to zero - e.append(m2_expr.ExprAssign(dst, dst)) - e_do, extra_irs = mov(ir, instr, dst, src) - e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) - e.append(m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) - return e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])] - - -def mov(_, instr, dst, src): - if dst in [ES, CS, SS, DS, FS, GS]: - src = src[:dst.size] - if src in [ES, CS, SS, DS, FS, GS]: - src = src.zeroExtend(dst.size) - e = [m2_expr.ExprAssign(dst, src)] - return e, [] - - -def movq(_, instr, dst, src): - src_final = (src.zeroExtend(dst.size) - if dst.size >= src.size else - src[:dst.size]) - return [m2_expr.ExprAssign(dst, src_final)], [] - - -@sbuild.parse -def xchg(arg1, arg2): - arg1 = arg2 - arg2 = arg1 - - - -def movzx(_, instr, dst, src): - e = [m2_expr.ExprAssign(dst, src.zeroExtend(dst.size))] - return e, [] - - -def movsx(_, instr, dst, src): - e = [m2_expr.ExprAssign(dst, src.signExtend(dst.size))] - return e, [] - - -def lea(_, instr, dst, src): - ptr = src.ptr - if is_mem_segm(src): - # Do not use segmentation here - ptr = ptr.args[1] - - if ptr.size > dst.size: - ptr = ptr[:dst.size] - e = [m2_expr.ExprAssign(dst, ptr.zeroExtend(dst.size))] - return e, [] - - -def add(_, instr, dst, src): - e = [] - - result = dst + src - - e += update_flag_arith_add_znp(dst, src) - e += update_flag_arith_add_co(dst, src, result) - e += update_flag_af(dst, src, result) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def xadd(_, instr, dst, src): - e = [] - - result = dst + src - e += update_flag_arith_add_znp(dst, src) - e += update_flag_arith_add_co(src, dst, result) - e += update_flag_af(dst, src, result) - if dst != src: - e.append(m2_expr.ExprAssign(src, dst)) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def adc(_, instr, dst, src): - e = [] - - arg1 = dst - arg2 = src - result = arg1 + (arg2 + cf.zeroExtend(src.size)) - - e += update_flag_arith_addwc_znp(arg1, arg2, cf) - e += update_flag_arith_addwc_co(arg1, arg2, cf) - e += update_flag_af(arg1, arg2, result) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def sub(_, instr, dst, src): - e = [] - arg1, arg2 = dst, src - result = dst - src - - e += update_flag_arith_sub_znp(arg1, arg2) - e += update_flag_arith_sub_co(arg1, arg2, result) - e += update_flag_af(dst, src, result) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -# a-(b+cf) - - -def sbb(_, instr, dst, src): - e = [] - arg1 = dst - arg2 = src - result = arg1 - (arg2 + cf.zeroExtend(src.size)) - - e += update_flag_arith_subwc_znp(arg1, arg2, cf) - e += update_flag_af(arg1, arg2, result) - e += update_flag_arith_subwc_co(arg1, arg2, cf) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def neg(_, instr, src): - e = [] - dst = m2_expr.ExprInt(0, src.size) - arg1, arg2 = dst, src - result = arg1 - arg2 - - e += update_flag_arith_sub_znp(arg1, arg2) - e += update_flag_arith_sub_co(arg1, arg2, result) - e += update_flag_af(arg1, arg2, result) - e.append(m2_expr.ExprAssign(src, result)) - return (e, []) - - -def l_not(_, instr, dst): - e = [] - result = (~dst) - e.append(m2_expr.ExprAssign(dst, result)) - return (e, []) - - -def l_cmp(_, instr, dst, src): - e = [] - arg1, arg2 = dst, src - result = dst - src - - e += update_flag_arith_sub_znp(arg1, arg2) - e += update_flag_arith_sub_co(arg1, arg2, result) - e += update_flag_af(dst, src, result) - return (e, []) - - -def xor(_, instr, dst, src): - e = [] - result = dst ^ src - e += [m2_expr.ExprAssign(zf, m2_expr.ExprOp('FLAG_EQ_CMP', dst, src))] - e += update_flag_np(result) - e += null_flag_co() - e.append(m2_expr.ExprAssign(dst, result)) - return (e, []) - - -def pxor(_, instr, dst, src): - e = [] - result = dst ^ src - e.append(m2_expr.ExprAssign(dst, result)) - return (e, []) - - -def l_or(_, instr, dst, src): - e = [] - result = dst | src - e += [m2_expr.ExprAssign(zf, m2_expr.ExprOp('FLAG_EQ', dst | src))] - e += update_flag_np(result) - e += null_flag_co() - e.append(m2_expr.ExprAssign(dst, result)) - return (e, []) - - -def l_and(_, instr, dst, src): - e = [] - result = dst & src - e += [m2_expr.ExprAssign(zf, m2_expr.ExprOp('FLAG_EQ_AND', dst, src))] - e += update_flag_np(result) - e += null_flag_co() - - e.append(m2_expr.ExprAssign(dst, result)) - return (e, []) - - -def l_test(_, instr, dst, src): - e = [] - result = dst & src - - e += [m2_expr.ExprAssign(zf, m2_expr.ExprOp('FLAG_EQ_CMP', result, m2_expr.ExprInt(0, result.size)))] - e += [m2_expr.ExprAssign(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", result, m2_expr.ExprInt(0, result.size)))] - e += update_flag_pf(result) - e += null_flag_co() - - return (e, []) - - -def get_shift(dst, src): - if isinstance(src, m2_expr.ExprInt): - src = m2_expr.ExprInt(int(src), dst.size) - else: - src = src.zeroExtend(dst.size) - if dst.size == 64: - shift = src & m2_expr.ExprInt(63, src.size) - else: - shift = src & m2_expr.ExprInt(31, src.size) - shift = expr_simp(shift) - return shift - - -def _rotate_tpl(ir, instr, dst, src, op, left=False): - '''Template to generate a rotater with operation @op - A temporary basic block is generated to handle 0-rotate - @op: operation to execute - @left (optional): indicates a left rotate if set, default is False - ''' - # Compute results - shifter = get_shift(dst, src) - res = m2_expr.ExprOp(op, dst, shifter) - - # CF is computed with 1-less round than `res` - new_cf = m2_expr.ExprOp( - op, dst, shifter - m2_expr.ExprInt(1, size=shifter.size)) - new_cf = new_cf.msb() if left else new_cf[:1] - - # OF is defined only for @b == 1 - new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), - m2_expr.ExprInt(0, size=of.size), - res.msb() ^ new_cf if left else (dst ^ res).msb()) - - # Build basic blocks - e_do = [m2_expr.ExprAssign(cf, new_cf), - m2_expr.ExprAssign(of, new_of), - m2_expr.ExprAssign(dst, res) - ] - e = [] - if instr.mode == 64: - # Force destination set in order to zero high bit orders - # In 64 bit: - # rol eax, cl - # if cl == 0 => high part of RAX is set to zero - e.append(m2_expr.ExprAssign(dst, dst)) - # Don't generate conditional shifter on constant - if isinstance(shifter, m2_expr.ExprInt): - if int(shifter) != 0: - return (e_do, []) - else: - return (e, []) - loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_skip = ir.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) - e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) - e.append(m2_expr.ExprAssign( - ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) - return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])]) - - -def l_rol(ir, instr, dst, src): - return _rotate_tpl(ir, instr, dst, src, '<<<', left=True) - - -def l_ror(ir, instr, dst, src): - return _rotate_tpl(ir, instr, dst, src, '>>>') - - -def rotate_with_carry_tpl(ir, instr, op, dst, src): - # Compute results - shifter = get_shift(dst, src).zeroExtend(dst.size + 1) - result = m2_expr.ExprOp(op, m2_expr.ExprCompose(dst, cf), shifter) - - new_cf = result[dst.size:dst.size +1] - new_dst = result[:dst.size] - - result_trunc = result[:dst.size] - if op == '<<<': - of_value = result_trunc.msb() ^ new_cf - else: - of_value = (dst ^ result_trunc).msb() - # OF is defined only for @b == 1 - new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), - m2_expr.ExprInt(0, size=of.size), - of_value) - - - # Build basic blocks - e_do = [m2_expr.ExprAssign(cf, new_cf), - m2_expr.ExprAssign(of, new_of), - m2_expr.ExprAssign(dst, new_dst) - ] - e = [m2_expr.ExprAssign(dst, dst)] - # Don't generate conditional shifter on constant - if isinstance(shifter, m2_expr.ExprInt): - if int(shifter) != 0: - return (e_do, []) - else: - return (e, []) - loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_skip = ir.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) - e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) - e.append(m2_expr.ExprAssign( - ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) - return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])]) - -def rcl(ir, instr, dst, src): - return rotate_with_carry_tpl(ir, instr, '<<<', dst, src) - -def rcr(ir, instr, dst, src): - return rotate_with_carry_tpl(ir, instr, '>>>', dst, src) - - -def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, - custom_of=None): - """Template to generate a shifter with operation @op - A temporary basic block is generated to handle 0-shift - @op: operation to execute - @c (optional): if set, instruction has a bit provider - @op_inv (optional): opposite operation of @op. Must be provided if @c - @left (optional): indicates a left shift if set, default is False - @custom_of (optional): if set, override the computed value of OF - """ - if c is not None: - shifter = get_shift(a, c) - else: - shifter = get_shift(a, b) - - res = m2_expr.ExprOp(op, a, shifter) - cf_from_dst = m2_expr.ExprOp(op, a, - (shifter - m2_expr.ExprInt(1, a.size))) - cf_from_dst = cf_from_dst.msb() if left else cf_from_dst[:1] - - new_cf = cf_from_dst - i1 = m2_expr.ExprInt(1, size=a.size) - if c is not None: - # There is a source for new bits - isize = m2_expr.ExprInt(a.size, size=a.size) - mask = m2_expr.ExprOp(op_inv, i1, (isize - shifter)) - i1 - - # An overflow can occurred, emulate the 'undefined behavior' - # Overflow behavior if (shift / size % 2) - base_cond_overflow = shifter if left else ( - shifter - m2_expr.ExprInt(1, size=shifter.size)) - cond_overflow = base_cond_overflow & m2_expr.ExprInt(a.size, shifter.size) - if left: - # Overflow occurs one round before right - mask = m2_expr.ExprCond(cond_overflow, mask, ~mask) - else: - mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) - - # Build res with dst and src - res = ((m2_expr.ExprOp(op, a, shifter) & mask) | - (m2_expr.ExprOp(op_inv, b, (isize - shifter)) & ~mask)) - - # Overflow case: cf come from src (bit number shifter % size) - cf_from_src = m2_expr.ExprOp(op, b, - (shifter.zeroExtend(b.size) & - m2_expr.ExprInt(a.size - 1, b.size)) - i1) - cf_from_src = cf_from_src.msb() if left else cf_from_src[:1] - new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) - - # Overflow flag, only occurred when shifter is equal to 1 - if custom_of is None: - value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() - else: - value_of = custom_of - - # Build basic blocks - e_do = [ - m2_expr.ExprAssign(cf, new_cf), - m2_expr.ExprAssign(of, m2_expr.ExprCond(shifter - i1, - m2_expr.ExprInt(0, of.size), - value_of)), - m2_expr.ExprAssign(a, res), - ] - e_do += update_flag_znp(res) - e = [] - if instr.mode == 64: - # Force destination set in order to zero high bit orders - # In 64 bit: - # shr eax, cl - # if cl == 0 => high part of RAX is set to zero - e.append(m2_expr.ExprAssign(a, a)) - # Don't generate conditional shifter on constant - if isinstance(shifter, m2_expr.ExprInt): - if int(shifter) != 0: - return (e_do, []) - else: - return (e, []) - loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_skip = ir.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) - e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) - e.append(m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, - loc_skip_expr))) - return e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])] - - -def sar(ir, instr, dst, src): - # Fixup OF, always cleared if src != 0 - i0 = m2_expr.ExprInt(0, size=of.size) - return _shift_tpl("a>>", ir, instr, dst, src, custom_of=i0) - - -def shr(ir, instr, dst, src): - return _shift_tpl(">>", ir, instr, dst, src, custom_of=dst.msb()) - - -def shrd(ir, instr, dst, src1, src2): - return _shift_tpl(">>>", ir, instr, dst, src1, src2, "<<<") - - -def shl(ir, instr, dst, src): - return _shift_tpl("<<", ir, instr, dst, src, left=True) - - -def shld(ir, instr, dst, src1, src2): - return _shift_tpl("<<<", ir, instr, dst, src1, src2, ">>>", left=True) - - -# XXX todo ### -def cmc(_, instr): - e = [m2_expr.ExprAssign(cf, m2_expr.ExprCond(cf, m2_expr.ExprInt(0, cf.size), - m2_expr.ExprInt(1, cf.size)))] - return e, [] - - -def clc(_, instr): - e = [m2_expr.ExprAssign(cf, m2_expr.ExprInt(0, cf.size))] - return e, [] - - -def stc(_, instr): - e = [m2_expr.ExprAssign(cf, m2_expr.ExprInt(1, cf.size))] - return e, [] - - -def cld(_, instr): - e = [m2_expr.ExprAssign(df, m2_expr.ExprInt(0, df.size))] - return e, [] - - -def std(_, instr): - e = [m2_expr.ExprAssign(df, m2_expr.ExprInt(1, df.size))] - return e, [] - - -def cli(_, instr): - e = [m2_expr.ExprAssign(i_f, m2_expr.ExprInt(0, i_f.size))] - return e, [] - - -def sti(_, instr): - e = [m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))] - return e, [] - - -def inc(_, instr, dst): - e = [] - src = m2_expr.ExprInt(1, dst.size) - arg1, arg2 = dst, src - result = dst + src - - e += update_flag_arith_add_znp(arg1, arg2) - e += update_flag_af(arg1, arg2, result) - e += update_flag_add_of(arg1, arg2, result) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def dec(_, instr, dst): - e = [] - src = m2_expr.ExprInt(1, dst.size) - arg1, arg2 = dst, src - result = dst - src - - e += update_flag_arith_sub_znp(arg1, arg2) - e += update_flag_af(arg1, arg2, result) - e += update_flag_sub_of(arg1, arg2, result) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def push_gen(ir, instr, src, size): - e = [] - if not size in [16, 32, 64]: - raise ValueError('bad size stacker!') - if src.size < size: - src = src.zeroExtend(size) - off_size = src.size - - sp = mRSP[instr.mode] - new_sp = sp - m2_expr.ExprInt(off_size // 8, sp.size) - e.append(m2_expr.ExprAssign(sp, new_sp)) - if ir.do_stk_segm: - new_sp = ir.gen_segm_expr(SS, new_sp) - e.append(m2_expr.ExprAssign(ir.ExprMem(new_sp, off_size), - src)) - return e, [] - - -def push(ir, instr, src): - return push_gen(ir, instr, src, instr.mode) - - -def pushw(ir, instr, src): - return push_gen(ir, instr, src, 16) - - -def pop_gen(ir, instr, src, size): - e = [] - if not size in [16, 32, 64]: - raise ValueError('bad size stacker!') - - sp = mRSP[instr.mode] - new_sp = sp + m2_expr.ExprInt(src.size // 8, sp.size) - # Don't generate SP/ESP/RSP incrementation on POP SP/ESP/RSP - if not (src in mRSP.values()): - e.append(m2_expr.ExprAssign(sp, new_sp)) - # XXX FIX XXX for pop [esp] - if isinstance(src, m2_expr.ExprMem): - src = expr_simp(src.replace_expr({sp: new_sp})) - result = sp - if ir.do_stk_segm: - result = ir.gen_segm_expr(SS, result) - - e.append(m2_expr.ExprAssign(src, ir.ExprMem(result, src.size))) - return e, [] - - -def pop(ir, instr, src): - return pop_gen(ir, instr, src, instr.mode) - - -def popw(ir, instr, src): - return pop_gen(ir, instr, src, 16) - - -def sete(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_EQ", zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setnz(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_EQ", ~zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setl(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_S<", nf, of).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setg(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_S>", nf, of, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setge(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_S>=", nf, of).zeroExtend(dst.size), - ) - ) - return e, [] - - -def seta(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setae(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setb(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U<", cf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setbe(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setns(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_NEG", ~nf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def sets(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_NEG", nf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def seto(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - of.zeroExtend(dst.size) - ) - ) - return e, [] - - -def setp(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - pf.zeroExtend(dst.size) - ) - ) - return e, [] - - -def setnp(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprCond( - pf, - m2_expr.ExprInt(0, dst.size), - m2_expr.ExprInt(1, dst.size) - ) - ) - ) - return e, [] - - -def setle(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_S<=", nf, of, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setna(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setnbe(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setno(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprCond( - of, - m2_expr.ExprInt(0, dst.size), - m2_expr.ExprInt(1, dst.size) - ) - ) - ) - return e, [] - - -def setnb(_, instr, dst): - e = [] - e.append( - m2_expr.ExprAssign( - dst, - m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), - ) - ) - return e, [] - - -def setalc(_, instr): - dst = mRAX[instr.mode][0:8] - e = [] - e.append( - m2_expr.ExprAssign(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(0xff, dst.size), - m2_expr.ExprInt(0, dst.size)))) - return e, [] - - -def bswap(_, instr, dst): - e = [] - if dst.size == 16: - # BSWAP referencing a 16-bit register is undefined - # Seems to return 0 actually - result = m2_expr.ExprInt(0, 16) - elif dst.size == 32: - result = m2_expr.ExprCompose( - dst[24:32], dst[16:24], dst[8:16], dst[:8]) - elif dst.size == 64: - result = m2_expr.ExprCompose(dst[56:64], dst[48:56], dst[40:48], dst[32:40], - dst[24:32], dst[16:24], dst[8:16], dst[:8]) - else: - raise ValueError('the size DOES matter') - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def cmps(ir, instr, size): - loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - src1 = mRSI[instr.mode][:instr.v_admode()] - src2 = mRDI[instr.mode][:instr.v_admode()] - - if ir.do_str_segm: - if instr.additional_info.g2.value: - raise NotImplementedError("add segm support") - src1_sgm = ir.gen_segm_expr(DS, src1) - src2_sgm = ir.gen_segm_expr(ES, src2) - else: - src1_sgm = src1 - src2_sgm = src2 - - offset = m2_expr.ExprInt(size // 8, src1.size) - - e, _ = l_cmp(ir, instr, - ir.ExprMem(src1_sgm, size), - ir.ExprMem(src2_sgm, size)) - - - e0 = [] - e0.append(m2_expr.ExprAssign(src1, src1 + offset)) - e0.append(m2_expr.ExprAssign(src2, src2 + offset)) - e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) - - e1 = [] - e1.append(m2_expr.ExprAssign(src1, src1 - offset)) - e1.append(m2_expr.ExprAssign(src2, src2 - offset)) - e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) - - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) - return e, [e0, e1] - - -def scas(ir, instr, size): - loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - src = mRDI[instr.mode][:instr.v_admode()] - - if ir.do_str_segm: - if instr.additional_info.g2.value: - raise NotImplementedError("add segm support") - src_sgm = ir.gen_segm_expr(ES, src) - - else: - src_sgm = src - - offset = m2_expr.ExprInt(size // 8, src.size) - e, extra = l_cmp(ir, instr, - mRAX[instr.mode][:size], - ir.ExprMem(src_sgm, size)) - - e0 = [] - e0.append(m2_expr.ExprAssign(src, src + offset)) - - e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) - - e1 = [] - e1.append(m2_expr.ExprAssign(src, src - offset)) - e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) - - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) - - return e, [e0, e1] - - -def compose_eflag(s=32): - args = [] - - args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, - m2_expr.ExprInt(0, 1), zf, nf, tf, i_f, df, of, iopl] - - if s == 32: - args += [nt, m2_expr.ExprInt(0, 1), rf, vm, ac, vif, vip, i_d] - elif s == 16: - args += [nt, m2_expr.ExprInt(0, 1)] - else: - raise ValueError('unk size') - if s == 32: - args.append(m2_expr.ExprInt(0, 10)) - return m2_expr.ExprCompose(*args) - - -def pushfd(ir, instr): - return push(ir, instr, compose_eflag()) - - -def pushfq(ir, instr): - return push(ir, instr, compose_eflag().zeroExtend(64)) - - -def pushfw(ir, instr): - return pushw(ir, instr, compose_eflag(16)) - - -def popfd(ir, instr): - tmp = ir.ExprMem(mRSP[instr.mode], 32) - e = [] - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprSlice(tmp, 0, 1))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprSlice(tmp, 2, 3))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprSlice(tmp, 4, 5))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprSlice(tmp, 6, 7))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprSlice(tmp, 7, 8))) - e.append(m2_expr.ExprAssign(tf, m2_expr.ExprSlice(tmp, 8, 9))) - e.append(m2_expr.ExprAssign(i_f, m2_expr.ExprSlice(tmp, 9, 10))) - e.append(m2_expr.ExprAssign(df, m2_expr.ExprSlice(tmp, 10, 11))) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprSlice(tmp, 11, 12))) - e.append(m2_expr.ExprAssign(iopl, m2_expr.ExprSlice(tmp, 12, 14))) - e.append(m2_expr.ExprAssign(nt, m2_expr.ExprSlice(tmp, 14, 15))) - e.append(m2_expr.ExprAssign(rf, m2_expr.ExprSlice(tmp, 16, 17))) - e.append(m2_expr.ExprAssign(vm, m2_expr.ExprSlice(tmp, 17, 18))) - e.append(m2_expr.ExprAssign(ac, m2_expr.ExprSlice(tmp, 18, 19))) - e.append(m2_expr.ExprAssign(vif, m2_expr.ExprSlice(tmp, 19, 20))) - e.append(m2_expr.ExprAssign(vip, m2_expr.ExprSlice(tmp, 20, 21))) - e.append(m2_expr.ExprAssign(i_d, m2_expr.ExprSlice(tmp, 21, 22))) - e.append(m2_expr.ExprAssign(mRSP[instr.mode], - mRSP[instr.mode] + m2_expr.ExprInt(instr.mode // 8, mRSP[instr.mode].size))) - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprCond(m2_expr.ExprSlice(tmp, 8, 9), - m2_expr.ExprInt( - EXCEPT_SOFT_BP, 32), - exception_flags - ) - ) - ) - return e, [] - - -def _tpl_eflags(tmp): - """Extract eflags from @tmp - @tmp: Expr instance with a size >= 16 - """ - return [m2_expr.ExprAssign(dest, tmp[base:base + dest.size]) - for base, dest in ((0, cf), (2, pf), (4, af), (6, zf), (7, nf), - (8, tf), (9, i_f), (10, df), (11, of), - (12, iopl), (14, nt))] - - -def popfw(ir, instr): - tmp = ir.ExprMem(mRSP[instr.mode], 16) - e = _tpl_eflags(tmp) - e.append( - m2_expr.ExprAssign(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(2, mRSP[instr.mode].size))) - return e, [] - -pa_regs = [ - mRAX, mRCX, - mRDX, mRBX, - mRSP, mRBP, - mRSI, mRDI -] - - -def pusha_gen(ir, instr, size): - e = [] - cur_sp = mRSP[instr.mode] - for i, reg in enumerate(pa_regs): - stk_ptr = cur_sp + m2_expr.ExprInt(-(size // 8) * (i + 1), instr.mode) - e.append(m2_expr.ExprAssign(ir.ExprMem(stk_ptr, size), reg[size])) - e.append(m2_expr.ExprAssign(cur_sp, stk_ptr)) - return e, [] - - -def pusha(ir, instr): - return pusha_gen(ir, instr, 16) - - -def pushad(ir, instr): - return pusha_gen(ir, instr, 32) - - -def popa_gen(ir, instr, size): - e = [] - cur_sp = mRSP[instr.mode] - for i, reg in enumerate(reversed(pa_regs)): - if reg == mRSP: - continue - stk_ptr = cur_sp + m2_expr.ExprInt((size // 8) * i, instr.mode) - e.append(m2_expr.ExprAssign(reg[size], ir.ExprMem(stk_ptr, size))) - - stk_ptr = cur_sp + m2_expr.ExprInt((size // 8) * (i + 1), instr.mode) - e.append(m2_expr.ExprAssign(cur_sp, stk_ptr)) - - return e, [] - - -def popa(ir, instr): - return popa_gen(ir, instr, 16) - - -def popad(ir, instr): - return popa_gen(ir, instr, 32) - - -def call(ir, instr, dst): - e = [] - # opmode, admode = instr.opmode, instr.admode - s = dst.size - meip = mRIP[ir.IRDst.size] - opmode, admode = s, instr.v_admode() - myesp = mRSP[instr.mode][:opmode] - n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - if isinstance(dst, m2_expr.ExprOp): - if dst.op == "segm": - # Far call segm:addr - if instr.mode not in [16, 32]: - raise RuntimeError('not supported') - segm = dst.args[0] - base = dst.args[1] - m1 = segm.zeroExtend(CS.size) - m2 = base.zeroExtend(meip.size) - elif dst.op == "far": - # Far call far [eax] - addr = dst.args[0].ptr - m1 = ir.ExprMem(addr, CS.size) - m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) - else: - raise RuntimeError("bad call operator") - - e.append(m2_expr.ExprAssign(CS, m1)) - e.append(m2_expr.ExprAssign(meip, m2)) - - e.append(m2_expr.ExprAssign(ir.IRDst, m2)) - - c = myesp + m2_expr.ExprInt(-s // 8, s) - e.append(m2_expr.ExprAssign(ir.ExprMem(c, size=s).zeroExtend(s), - CS.zeroExtend(s))) - - c = myesp + m2_expr.ExprInt((-2 * s) // 8, s) - e.append(m2_expr.ExprAssign(ir.ExprMem(c, size=s).zeroExtend(s), - meip.zeroExtend(s))) - - c = myesp + m2_expr.ExprInt((-2 * s) // 8, s) - e.append(m2_expr.ExprAssign(myesp, c)) - return e, [] - - c = myesp + m2_expr.ExprInt(-s // 8, s) - e.append(m2_expr.ExprAssign(myesp, c)) - if ir.do_stk_segm: - c = ir.gen_segm_expr(SS, c) - - e.append(m2_expr.ExprAssign(ir.ExprMem(c, size=s), n)) - e.append(m2_expr.ExprAssign(meip, dst.zeroExtend(ir.IRDst.size))) - e.append(m2_expr.ExprAssign(ir.IRDst, dst.zeroExtend(ir.IRDst.size))) - return e, [] - - -def ret(ir, instr, src=None): - e = [] - meip = mRIP[ir.IRDst.size] - size, admode = instr.v_opmode(), instr.v_admode() - myesp = mRSP[instr.mode][:size] - - if src is None: - value = (myesp + (m2_expr.ExprInt(size // 8, size))) - else: - src = m2_expr.ExprInt(int(src), size) - value = (myesp + (m2_expr.ExprInt(size // 8, size) + src)) - - e.append(m2_expr.ExprAssign(myesp, value)) - result = myesp - if ir.do_stk_segm: - result = ir.gen_segm_expr(SS, result) - - e.append(m2_expr.ExprAssign(meip, ir.ExprMem( - result, size=size).zeroExtend(size))) - e.append(m2_expr.ExprAssign(ir.IRDst, - ir.ExprMem(result, size=size).zeroExtend(size))) - return e, [] - - -def retf(ir, instr, src=None): - e = [] - meip = mRIP[ir.IRDst.size] - size, admode = instr.v_opmode(), instr.v_admode() - if src is None: - src = m2_expr.ExprInt(0, instr.mode) - myesp = mRSP[instr.mode][:size] - - src = src.zeroExtend(size) - - result = myesp - if ir.do_stk_segm: - result = ir.gen_segm_expr(SS, result) - - e.append(m2_expr.ExprAssign(meip, ir.ExprMem( - result, size=size).zeroExtend(size))) - e.append(m2_expr.ExprAssign(ir.IRDst, - ir.ExprMem(result, size=size).zeroExtend(size))) - # e.append(m2_expr.ExprAssign(meip, ir.ExprMem(c, size = s))) - result = myesp + m2_expr.ExprInt(size // 8, size) - if ir.do_stk_segm: - result = ir.gen_segm_expr(SS, result) - - e.append(m2_expr.ExprAssign(CS, ir.ExprMem(result, size=16))) - - value = myesp + (m2_expr.ExprInt((2 * size) // 8, size) + src) - e.append(m2_expr.ExprAssign(myesp, value)) - return e, [] - - -def leave(ir, instr): - size = instr.mode - myesp = mRSP[size] - e = [] - e.append(m2_expr.ExprAssign(mRBP[size], ir.ExprMem(mRBP[size], size=size))) - e.append(m2_expr.ExprAssign(myesp, - m2_expr.ExprInt(size // 8, size) + mRBP[size])) - return e, [] - - -def enter(ir, instr, src1, src2): - size, admode = instr.v_opmode(), instr.v_admode() - myesp = mRSP[instr.mode][:size] - myebp = mRBP[instr.mode][:size] - - src1 = src1.zeroExtend(size) - - e = [] - esp_tmp = myesp - m2_expr.ExprInt(size // 8, size) - e.append(m2_expr.ExprAssign(ir.ExprMem(esp_tmp, size=size), - myebp)) - e.append(m2_expr.ExprAssign(myebp, esp_tmp)) - e.append(m2_expr.ExprAssign(myesp, - myesp - (src1 + m2_expr.ExprInt(size // 8, size)))) - return e, [] - - -def jmp(ir, instr, dst): - e = [] - meip = mRIP[ir.IRDst.size] - - if isinstance(dst, m2_expr.ExprOp): - if dst.op == "segm": - # Far jmp segm:addr - segm = dst.args[0] - base = dst.args[1] - m1 = segm.zeroExtend(CS.size) - m2 = base.zeroExtend(meip.size) - elif dst.op == "far": - # Far jmp far [eax] - addr = dst.args[0].ptr - m1 = ir.ExprMem(addr, CS.size) - m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) - else: - raise RuntimeError("bad jmp operator") - - e.append(m2_expr.ExprAssign(CS, m1)) - e.append(m2_expr.ExprAssign(meip, m2)) - e.append(m2_expr.ExprAssign(ir.IRDst, m2)) - - else: - # Classic jmp - e.append(m2_expr.ExprAssign(meip, dst)) - e.append(m2_expr.ExprAssign(ir.IRDst, dst)) - - if isinstance(dst, m2_expr.ExprMem): - dst = meip - return e, [] - - -def jz(ir, instr, dst): - #return gen_jcc(ir, instr, zf, dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, True) - - -def jcxz(ir, instr, dst): - return gen_jcc(ir, instr, mRCX[instr.mode][:16], dst, False) - - -def jecxz(ir, instr, dst): - return gen_jcc(ir, instr, mRCX[instr.mode][:32], dst, False) - - -def jrcxz(ir, instr, dst): - return gen_jcc(ir, instr, mRCX[instr.mode], dst, False) - - -def jnz(ir, instr, dst): - #return gen_jcc(ir, instr, zf, dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, False) - - - -def jp(ir, instr, dst): - return gen_jcc(ir, instr, pf, dst, True) - - -def jnp(ir, instr, dst): - return gen_jcc(ir, instr, pf, dst, False) - - -def ja(ir, instr, dst): - #return gen_jcc(ir, instr, cf | zf, dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, True) - - -def jae(ir, instr, dst): - #return gen_jcc(ir, instr, cf, dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, True) - - -def jb(ir, instr, dst): - #return gen_jcc(ir, instr, cf, dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, True) - - -def jbe(ir, instr, dst): - #return gen_jcc(ir, instr, cf | zf, dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, True) - - -def jge(ir, instr, dst): - #return gen_jcc(ir, instr, nf - of, dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, True) - - -def jg(ir, instr, dst): - #return gen_jcc(ir, instr, zf | (nf - of), dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, True) - - -def jl(ir, instr, dst): - #return gen_jcc(ir, instr, nf - of, dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, True) - - -def jle(ir, instr, dst): - #return gen_jcc(ir, instr, zf | (nf - of), dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, True) - - - -def js(ir, instr, dst): - #return gen_jcc(ir, instr, nf, dst, True) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, True) - - - -def jns(ir, instr, dst): - #return gen_jcc(ir, instr, nf, dst, False) - return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, False) - - -def jo(ir, instr, dst): - return gen_jcc(ir, instr, of, dst, True) - - -def jno(ir, instr, dst): - return gen_jcc(ir, instr, of, dst, False) - - -def loop(ir, instr, dst): - e = [] - meip = mRIP[ir.IRDst.size] - admode = instr.v_admode() - myecx = mRCX[instr.mode][:admode] - - n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - c = myecx - m2_expr.ExprInt(1, myecx.size) - dst_o = m2_expr.ExprCond(c, - dst.zeroExtend(ir.IRDst.size), - n.zeroExtend(ir.IRDst.size)) - e.append(m2_expr.ExprAssign(myecx, c)) - e.append(m2_expr.ExprAssign(meip, dst_o)) - e.append(m2_expr.ExprAssign(ir.IRDst, dst_o)) - return e, [] - - -def loopne(ir, instr, dst): - e = [] - meip = mRIP[ir.IRDst.size] - admode = instr.v_admode() - myecx = mRCX[instr.mode][:admode] - - n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - c &= zf ^ m2_expr.ExprInt(1, 1) - - e.append(m2_expr.ExprAssign(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) - dst_o = m2_expr.ExprCond(c, - dst.zeroExtend(ir.IRDst.size), - n.zeroExtend(ir.IRDst.size)) - e.append(m2_expr.ExprAssign(meip, dst_o)) - e.append(m2_expr.ExprAssign(ir.IRDst, dst_o)) - return e, [] - - -def loope(ir, instr, dst): - e = [] - meip = mRIP[ir.IRDst.size] - admode = instr.v_admode() - myecx = mRCX[instr.mode][:admode] - - n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - c &= zf - e.append(m2_expr.ExprAssign(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) - dst_o = m2_expr.ExprCond(c, - dst.zeroExtend(ir.IRDst.size), - n.zeroExtend(ir.IRDst.size)) - e.append(m2_expr.ExprAssign(meip, dst_o)) - e.append(m2_expr.ExprAssign(ir.IRDst, dst_o)) - return e, [] - -# XXX size to do; eflag - - -def div(ir, instr, src1): - e = [] - size = src1.size - if size == 8: - src2 = mRAX[instr.mode][:16] - elif size in [16, 32, 64]: - s1, s2 = mRDX[size], mRAX[size] - src2 = m2_expr.ExprCompose(s2, s1) - else: - raise ValueError('div arg not impl', src1) - - c_d = m2_expr.ExprOp('udiv', src2, src1.zeroExtend(src2.size)) - c_r = m2_expr.ExprOp('umod', src2, src1.zeroExtend(src2.size)) - - # if 8 bit div, only ax is assigned - if size == 8: - e.append(m2_expr.ExprAssign(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) - else: - e.append(m2_expr.ExprAssign(s1, c_r[:size])) - e.append(m2_expr.ExprAssign(s2, c_d[:size])) - - loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) - - do_div = [] - do_div += e - do_div.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_div = IRBlock(ir.loc_db, loc_div, [AssignBlock(do_div, instr)]) - - do_except = [] - do_except.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt( - EXCEPT_DIV_BY_ZERO, exception_flags.size))) - do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_except = IRBlock(ir.loc_db, loc_except, [AssignBlock(do_except, instr)]) - - e = [] - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) - - return e, [blk_div, blk_except] - - -# XXX size to do; eflag - -def idiv(ir, instr, src1): - e = [] - size = src1.size - - if size == 8: - src2 = mRAX[instr.mode][:16] - elif size in [16, 32, 64]: - s1, s2 = mRDX[size], mRAX[size] - src2 = m2_expr.ExprCompose(s2, s1) - else: - raise ValueError('div arg not impl', src1) - - c_d = m2_expr.ExprOp('sdiv', src2, src1.signExtend(src2.size)) - c_r = m2_expr.ExprOp('smod', src2, src1.signExtend(src2.size)) - - # if 8 bit div, only ax is assigned - if size == 8: - e.append(m2_expr.ExprAssign(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) - else: - e.append(m2_expr.ExprAssign(s1, c_r[:size])) - e.append(m2_expr.ExprAssign(s2, c_d[:size])) - - loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) - - do_div = [] - do_div += e - do_div.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_div = IRBlock(ir.loc_db, loc_div, [AssignBlock(do_div, instr)]) - - do_except = [] - do_except.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt( - EXCEPT_DIV_BY_ZERO, exception_flags.size))) - do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_except = IRBlock(ir.loc_db, loc_except, [AssignBlock(do_except, instr)]) - - e = [] - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) - - return e, [blk_div, blk_except] - - -# XXX size to do; eflag - - -def mul(_, instr, src1): - e = [] - size = src1.size - if src1.size in [16, 32, 64]: - result = m2_expr.ExprOp('*', - mRAX[size].zeroExtend(size * 2), - src1.zeroExtend(size * 2)) - e.append(m2_expr.ExprAssign(mRAX[size], result[:size])) - e.append(m2_expr.ExprAssign(mRDX[size], result[size:size * 2])) - - elif src1.size == 8: - result = m2_expr.ExprOp('*', - mRAX[instr.mode][:8].zeroExtend(16), - src1.zeroExtend(16)) - e.append(m2_expr.ExprAssign(mRAX[instr.mode][:16], result)) - else: - raise ValueError('unknow size') - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprCond(result[size:size * 2], - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)))) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(result[size:size * 2], - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)))) - - return e, [] - - -def imul(_, instr, src1, src2=None, src3=None): - e = [] - size = src1.size - if src2 is None: - if size in [16, 32, 64]: - result = m2_expr.ExprOp('*', - mRAX[size].signExtend(size * 2), - src1.signExtend(size * 2)) - e.append(m2_expr.ExprAssign(mRAX[size], result[:size])) - e.append(m2_expr.ExprAssign(mRDX[size], result[size:size * 2])) - elif size == 8: - dst = mRAX[instr.mode][:16] - result = m2_expr.ExprOp('*', - mRAX[instr.mode][:8].signExtend(16), - src1.signExtend(16)) - - e.append(m2_expr.ExprAssign(dst, result)) - value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - e.append(m2_expr.ExprAssign(cf, value)) - value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - e.append(m2_expr.ExprAssign(of, value)) - - else: - if src3 is None: - src3 = src2 - src2 = src1 - result = m2_expr.ExprOp('*', - src2.signExtend(size * 2), - src3.signExtend(size * 2)) - e.append(m2_expr.ExprAssign(src1, result[:size])) - - value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - e.append(m2_expr.ExprAssign(cf, value)) - value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - e.append(m2_expr.ExprAssign(of, value)) - return e, [] - - -def cbw(_, instr): - # Only in 16 bit - e = [] - tempAL = mRAX[instr.v_opmode()][:8] - tempAX = mRAX[instr.v_opmode()][:16] - e.append(m2_expr.ExprAssign(tempAX, tempAL.signExtend(16))) - return e, [] - - -def cwde(_, instr): - # Only in 32/64 bit - e = [] - tempAX = mRAX[instr.v_opmode()][:16] - tempEAX = mRAX[instr.v_opmode()][:32] - e.append(m2_expr.ExprAssign(tempEAX, tempAX.signExtend(32))) - return e, [] - - -def cdqe(_, instr): - # Only in 64 bit - e = [] - tempEAX = mRAX[instr.mode][:32] - tempRAX = mRAX[instr.mode][:64] - e.append(m2_expr.ExprAssign(tempRAX, tempEAX.signExtend(64))) - return e, [] - - -def cwd(_, instr): - # Only in 16 bit - e = [] - tempAX = mRAX[instr.mode][:16] - tempDX = mRDX[instr.mode][:16] - result = tempAX.signExtend(32) - e.append(m2_expr.ExprAssign(tempAX, result[:16])) - e.append(m2_expr.ExprAssign(tempDX, result[16:32])) - return e, [] - - -def cdq(_, instr): - # Only in 32/64 bit - e = [] - tempEAX = mRAX[instr.v_opmode()] - tempEDX = mRDX[instr.v_opmode()] - result = tempEAX.signExtend(64) - e.append(m2_expr.ExprAssign(tempEDX, result[32:64])) - return e, [] - - -def cqo(_, instr): - # Only in 64 bit - e = [] - tempRAX = mRAX[instr.mode][:64] - tempRDX = mRDX[instr.mode][:64] - result = tempRAX.signExtend(128) - e.append(m2_expr.ExprAssign(tempRAX, result[:64])) - e.append(m2_expr.ExprAssign(tempRDX, result[64:128])) - return e, [] - - -def stos(ir, instr, size): - loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - addr_o = mRDI[instr.mode][:instr.v_admode()] - addr = addr_o - addr_p = addr + m2_expr.ExprInt(size // 8, addr.size) - addr_m = addr - m2_expr.ExprInt(size // 8, addr.size) - if ir.do_str_segm: - mss = ES - if instr.additional_info.g2.value: - raise NotImplementedError("add segm support") - addr = ir.gen_segm_expr(mss, addr) - - - b = mRAX[instr.mode][:size] - - e0 = [] - e0.append(m2_expr.ExprAssign(addr_o, addr_p)) - e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) - - e1 = [] - e1.append(m2_expr.ExprAssign(addr_o, addr_m)) - e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) - - e = [] - e.append(m2_expr.ExprAssign(ir.ExprMem(addr, size), b)) - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) - return e, [e0, e1] - - -def lods(ir, instr, size): - loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - e = [] - - addr_o = mRSI[instr.mode][:instr.v_admode()] - addr = addr_o - addr_p = addr + m2_expr.ExprInt(size // 8, addr.size) - addr_m = addr - m2_expr.ExprInt(size // 8, addr.size) - if ir.do_str_segm: - mss = DS - if instr.additional_info.g2.value: - raise NotImplementedError("add segm support") - addr = ir.gen_segm_expr(mss, addr) - - - b = mRAX[instr.mode][:size] - - e0 = [] - e0.append(m2_expr.ExprAssign(addr_o, addr_p)) - e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) - - e1 = [] - e1.append(m2_expr.ExprAssign(addr_o, addr_m)) - e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) - - e = [] - if instr.mode == 64 and b.size == 32: - e.append(m2_expr.ExprAssign(mRAX[instr.mode], - ir.ExprMem(addr, size).zeroExtend(64))) - else: - e.append(m2_expr.ExprAssign(b, ir.ExprMem(addr, size))) - - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) - return e, [e0, e1] - - -def movs(ir, instr, size): - loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) - - dst = mRDI[instr.mode][:instr.v_admode()] - src = mRSI[instr.mode][:instr.v_admode()] - - e = [] - if ir.do_str_segm: - if instr.additional_info.g2.value: - raise NotImplementedError("add segm support") - src_sgm = ir.gen_segm_expr(DS, src) - dst_sgm = ir.gen_segm_expr(ES, dst) - - else: - src_sgm = src - dst_sgm = dst - - offset = m2_expr.ExprInt(size // 8, src.size) - - e.append(m2_expr.ExprAssign(ir.ExprMem(dst_sgm, size), - ir.ExprMem(src_sgm, size))) - - e0 = [] - e0.append(m2_expr.ExprAssign(src, src + offset)) - e0.append(m2_expr.ExprAssign(dst, dst + offset)) - e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) - - e1 = [] - e1.append(m2_expr.ExprAssign(src, src - offset)) - e1.append(m2_expr.ExprAssign(dst, dst - offset)) - e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) - - e.append(m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) - return e, [e0, e1] - - -def movsd(_, instr, dst, src): - # 64 bits access - if dst.is_id() and src.is_id(): - src = src[:64] - dst = dst[:64] - elif dst.is_mem() and src.is_id(): - dst = m2_expr.ExprMem(dst.ptr, 64) - src = src[:64] - else: - src = m2_expr.ExprMem(src.ptr, 64) - # Erase dst high bits - src = src.zeroExtend(dst.size) - return [m2_expr.ExprAssign(dst, src)], [] - - -def movsd_dispatch(ir, instr, dst=None, src=None): - if dst is None and src is None: - return movs(ir, instr, 32) - else: - return movsd(ir, instr, dst, src) - - -def float_prev(flt, popcount=1): - if not flt in float_list: - return None - i = float_list.index(flt) - if i < popcount: - # Drop value (ex: FSTP ST(0)) - return None - flt = float_list[i - popcount] - return flt - - -def float_pop(avoid_flt=None, popcount=1): - """ - Generate floatpop semantic (@popcount times), avoiding the avoid_flt@ float - @avoid_flt: float avoided in the generated semantic - @popcount: pop count - """ - avoid_flt = float_prev(avoid_flt, popcount) - e = [] - for i in range(8 - popcount): - if avoid_flt != float_list[i]: - e.append(m2_expr.ExprAssign(float_list[i], - float_list[i + popcount])) - fill_value = m2_expr.ExprOp("sint_to_fp", m2_expr.ExprInt(0, 64)) - for i in range(8 - popcount, 8): - e.append(m2_expr.ExprAssign(float_list[i], - fill_value)) - e.append( - m2_expr.ExprAssign(float_stack_ptr, - float_stack_ptr - m2_expr.ExprInt(popcount, 3))) - return e - -# XXX TODO - - -def fcom(_, instr, dst=None, src=None): - - if dst is None and src is None: - dst, src = float_st0, float_st1 - elif src is None: - src = mem2double(instr, dst) - dst = float_st0 - - e = [] - - e.append(m2_expr.ExprAssign(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) - e.append(m2_expr.ExprAssign(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) - e.append(m2_expr.ExprAssign(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) - e.append(m2_expr.ExprAssign(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) - - e += set_float_cs_eip(instr) - return e, [] - - -def ftst(_, instr): - dst = float_st0 - - e = [] - src = m2_expr.ExprOp('sint_to_fp', m2_expr.ExprInt(0, 64)) - e.append(m2_expr.ExprAssign(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) - e.append(m2_expr.ExprAssign(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) - e.append(m2_expr.ExprAssign(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) - e.append(m2_expr.ExprAssign(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fxam(ir, instr): - """ - NaN: - C3, C2, C0 = 001; - Normal: - C3, C2, C0 = 010; - Infinity: - C3, C2, C0 = 011; - Zero: - C3, C2, C0 = 100; - Empty: - C3, C2, C0 = 101; - Denormal: - C3, C2, C0 = 110; - - C1 = sign bit of ST; (* 0 for positive, 1 for negative *) - """ - dst = float_st0 - - # Empty not handled - locs = {} - for name in ["NaN", "Normal", "Infinity", "Zero", "Denormal"]: - locs[name] = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) - - # if Denormal: - # if zero: - # do_zero - # else: - # do_denormal - # else: - # if Nan: - # do_nan - # else: - # if infinity: - # do_infinity - # else: - # do_normal - - irdst = m2_expr.ExprCond( - m2_expr.expr_is_IEEE754_denormal(dst), - m2_expr.ExprCond(m2_expr.expr_is_IEEE754_zero(dst), - locs["Zero"][1], - locs["Denormal"][1], - ), - m2_expr.ExprCond(m2_expr.expr_is_NaN(dst), - locs["NaN"][1], - m2_expr.ExprCond(m2_expr.expr_is_infinite(dst), - locs["Infinity"][1], - locs["Normal"][1], - ) - ) - ) - base = [m2_expr.ExprAssign(ir.IRDst, irdst), - m2_expr.ExprAssign(float_c1, dst.msb()) - ] - base += set_float_cs_eip(instr) - - out = [ - IRBlock(ir.loc_db, locs["Zero"][0], [AssignBlock({ - float_c0: m2_expr.ExprInt(0, float_c0.size), - float_c2: m2_expr.ExprInt(0, float_c2.size), - float_c3: m2_expr.ExprInt(1, float_c3.size), - ir.IRDst: loc_next_expr, - }, instr)]), - IRBlock(ir.loc_db, locs["Denormal"][0], [AssignBlock({ - float_c0: m2_expr.ExprInt(0, float_c0.size), - float_c2: m2_expr.ExprInt(1, float_c2.size), - float_c3: m2_expr.ExprInt(1, float_c3.size), - ir.IRDst: loc_next_expr, - }, instr)]), - IRBlock(ir.loc_db, locs["NaN"][0], [AssignBlock({ - float_c0: m2_expr.ExprInt(1, float_c0.size), - float_c2: m2_expr.ExprInt(0, float_c2.size), - float_c3: m2_expr.ExprInt(0, float_c3.size), - ir.IRDst: loc_next_expr, - }, instr)]), - IRBlock(ir.loc_db, locs["Infinity"][0], [AssignBlock({ - float_c0: m2_expr.ExprInt(1, float_c0.size), - float_c2: m2_expr.ExprInt(1, float_c2.size), - float_c3: m2_expr.ExprInt(0, float_c3.size), - ir.IRDst: loc_next_expr, - }, instr)]), - IRBlock(ir.loc_db, locs["Normal"][0], [AssignBlock({ - float_c0: m2_expr.ExprInt(0, float_c0.size), - float_c2: m2_expr.ExprInt(1, float_c2.size), - float_c3: m2_expr.ExprInt(0, float_c3.size), - ir.IRDst: loc_next_expr, - }, instr)]), - ] - return base, out - - -def ficom(_, instr, dst, src=None): - - dst, src = float_implicit_st0(dst, src) - - e = [] - - e.append(m2_expr.ExprAssign(float_c0, - m2_expr.ExprOp('fcom_c0', dst, - src.zeroExtend(dst.size)))) - e.append(m2_expr.ExprAssign(float_c1, - m2_expr.ExprOp('fcom_c1', dst, - src.zeroExtend(dst.size)))) - e.append(m2_expr.ExprAssign(float_c2, - m2_expr.ExprOp('fcom_c2', dst, - src.zeroExtend(dst.size)))) - e.append(m2_expr.ExprAssign(float_c3, - m2_expr.ExprOp('fcom_c3', dst, - src.zeroExtend(dst.size)))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fcomi(_, instr, dst=None, src=None): - # TODO unordered float - if dst is None and src is None: - dst, src = float_st0, float_st1 - elif src is None: - src = dst - dst = float_st0 - - e = [] - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprOp('fcom_c0', dst, src))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprOp('fcom_c2', dst, src))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp('fcom_c3', dst, src))) - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fcomip(ir, instr, dst=None, src=None): - e, extra = fcomi(ir, instr, dst, src) - e += float_pop() - e += set_float_cs_eip(instr) - return e, extra - - -def fucomi(ir, instr, dst=None, src=None): - # TODO unordered float - return fcomi(ir, instr, dst, src) - - -def fucomip(ir, instr, dst=None, src=None): - # TODO unordered float - return fcomip(ir, instr, dst, src) - - -def fcomp(ir, instr, dst=None, src=None): - e, extra = fcom(ir, instr, dst, src) - e += float_pop() - e += set_float_cs_eip(instr) - return e, extra - - -def fcompp(ir, instr, dst=None, src=None): - e, extra = fcom(ir, instr, dst, src) - e += float_pop(popcount=2) - e += set_float_cs_eip(instr) - return e, extra - - -def ficomp(ir, instr, dst, src=None): - e, extra = ficom(ir, instr, dst, src) - e += float_pop() - e += set_float_cs_eip(instr) - return e, extra - - -def fucom(ir, instr, dst=None, src=None): - # TODO unordered float - return fcom(ir, instr, dst, src) - - -def fucomp(ir, instr, dst=None, src=None): - # TODO unordered float - return fcomp(ir, instr, dst, src) - - -def fucompp(ir, instr, dst=None, src=None): - # TODO unordered float - return fcompp(ir, instr, dst, src) - - -def comiss(_, instr, dst, src): - # TODO unordered float - - e = [] - - dst = m2_expr.ExprOp('sint_to_fp', dst[:32]) - src = m2_expr.ExprOp('sint_to_fp', src[:32]) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprOp('fcom_c0', dst, src))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprOp('fcom_c2', dst, src))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp('fcom_c3', dst, src))) - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - - e += set_float_cs_eip(instr) - return e, [] - - -def comisd(_, instr, dst, src): - # TODO unordered float - - e = [] - - dst = m2_expr.ExprOp('sint_to_fp', dst[:64]) - src = m2_expr.ExprOp('sint_to_fp', src[:64]) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprOp('fcom_c0', dst, src))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprOp('fcom_c2', dst, src))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp('fcom_c3', dst, src))) - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fld(_, instr, src): - - if src.size == 32: - src = m2_expr.ExprOp("fpconvert_fp64", src) - if isinstance(src, m2_expr.ExprMem) and src.size > 64: - raise NotImplementedError('convert from 80bits') - - e = [] - e.append(m2_expr.ExprAssign(float_st7, float_st6)) - e.append(m2_expr.ExprAssign(float_st6, float_st5)) - e.append(m2_expr.ExprAssign(float_st5, float_st4)) - e.append(m2_expr.ExprAssign(float_st4, float_st3)) - e.append(m2_expr.ExprAssign(float_st3, float_st2)) - e.append(m2_expr.ExprAssign(float_st2, float_st1)) - e.append(m2_expr.ExprAssign(float_st1, float_st0)) - e.append(m2_expr.ExprAssign(float_st0, src)) - e.append( - m2_expr.ExprAssign(float_stack_ptr, - float_stack_ptr + m2_expr.ExprInt(1, 3))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fst(_, instr, dst): - e = [] - - if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: - raise NotImplementedError('convert to 80bits') - src = float_st0 - - if dst.size == 32: - src = m2_expr.ExprOp("fpconvert_fp32", src) - e.append(m2_expr.ExprAssign(dst, src)) - e += set_float_cs_eip(instr) - return e, [] - - -def fstp(ir, instr, dst): - e = [] - - if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: - raise NotImplementedError('convert to 80bits') - - if isinstance(dst, m2_expr.ExprMem): - src = float_st0 - if dst.size == 32: - src = m2_expr.ExprOp("fpconvert_fp32", src) - e.append(m2_expr.ExprAssign(dst, src)) - else: - src = float_st0 - if float_list.index(dst) > 1: - # a = st0 -> st0 is dropped - # a = st1 -> st0 = st0, useless - e.append(m2_expr.ExprAssign(float_prev(dst), src)) - - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fist(_, instr, dst): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fp_to_sint%d' % dst.size, - float_st0))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fistp(ir, instr, dst): - e, extra = fist(ir, instr, dst) - e += float_pop(dst) - return e, extra - - -def fisttp(_, instr, dst): - e = [] - e.append(m2_expr.ExprAssign( - dst, - m2_expr.ExprOp('fp_to_sint%d' % dst.size, - m2_expr.ExprOp('fpround_towardszero', float_st0) - ))) - - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fild(ir, instr, src): - # XXXXX - src = m2_expr.ExprOp('sint_to_fp', src.signExtend(64)) - e = [] - e += set_float_cs_eip(instr) - e_fld, extra = fld(ir, instr, src) - e += e_fld - return e, extra - - -def fldz(ir, instr): - return fld(ir, instr, m2_expr.ExprOp('sint_to_fp', m2_expr.ExprInt(0, 64))) - - -def fld1(ir, instr): - return fld(ir, instr, m2_expr.ExprOp('sint_to_fp', m2_expr.ExprInt(1, 64))) - - -def fldl2t(ir, instr): - value_f = math.log(10) / math.log(2) - value = struct.unpack('Q', struct.pack('d', value_f))[0] - return fld(ir, instr, m2_expr.ExprOp( - 'sint_to_fp', - m2_expr.ExprInt(value, 64) - )) - - -def fldpi(ir, instr): - value_f = math.pi - value = struct.unpack('Q', struct.pack('d', value_f))[0] - return fld(ir, instr, m2_expr.ExprOp( - 'sint_to_fp', - m2_expr.ExprInt(value, 64) - )) - - -def fldln2(ir, instr): - value_f = math.log(2) - value = struct.unpack('Q', struct.pack('d', value_f))[0] - return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', - m2_expr.ExprInt(value, 64))) - - -def fldl2e(ir, instr): - x = struct.pack('d', 1 / math.log(2)) - x = struct.unpack('Q', x)[0] - return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', - m2_expr.ExprInt(x, 64))) - - -def fldlg2(ir, instr): - x = struct.pack('d', math.log10(2)) - x = struct.unpack('Q', x)[0] - return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', - m2_expr.ExprInt(x, 64))) - - -def fadd(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fadd', dst, src))) - - e += set_float_cs_eip(instr) - return e, [] - - -def fiadd(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fiadd', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fisub(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fisub', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fisubr(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fisub', src, dst))) - e += set_float_cs_eip(instr) - return e, [] - - -def fpatan(_, instr): - e = [] - a = float_st1 - e.append(m2_expr.ExprAssign(float_prev(a), - m2_expr.ExprOp('fpatan', float_st0, float_st1))) - e += set_float_cs_eip(instr) - e += float_pop(a) - return e, [] - - -def fprem(_, instr): - e = [] - e.append( - m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fprem', float_st0, float_st1))) - # Remaining bits (ex: used in argument reduction in tan) - quotient = m2_expr.ExprOp('fp_to_sint32', m2_expr.ExprOp('fpround_towardszero', m2_expr.ExprOp('fdiv', float_st0, float_st1))) - e += [m2_expr.ExprAssign(float_c0, quotient[2:3]), - m2_expr.ExprAssign(float_c3, quotient[1:2]), - m2_expr.ExprAssign(float_c1, quotient[0:1]), - # Consider the reduction is always completed - m2_expr.ExprAssign(float_c2, m2_expr.ExprInt(0, 1)), - ] - e += set_float_cs_eip(instr) - return e, [] - - -def fprem1(_, instr): - e = [] - e.append( - m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fprem1', float_st0, float_st1))) - e += set_float_cs_eip(instr) - return e, [] - - -def faddp(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fadd', dst, src))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fninit(_, instr): - e = [] - e += set_float_cs_eip(instr) - return e, [] - - -def fyl2x(_, instr): - e = [] - a = float_st1 - e.append( - m2_expr.ExprAssign(float_prev(a), m2_expr.ExprOp('fyl2x', float_st0, float_st1))) - e += set_float_cs_eip(instr) - e += float_pop(a) - return e, [] - - -def fnstenv(ir, instr, dst): - e = [] - # XXX TODO tag word, ... - status_word = m2_expr.ExprCompose(m2_expr.ExprInt(0, 8), - float_c0, float_c1, float_c2, - float_stack_ptr, float_c3, - m2_expr.ExprInt(0, 1)) - - s = instr.mode - # The behaviour in 64bit is identical to 32 bit - # This will truncate addresses - size = min(32, s) - ad = ir.ExprMem(dst.ptr, size=16) - e.append(m2_expr.ExprAssign(ad, float_control)) - ad = ir.ExprMem( - dst.ptr + m2_expr.ExprInt( - (size // 8) * 1, - dst.ptr.size - ), - size=16 - ) - e.append(m2_expr.ExprAssign(ad, status_word)) - ad = ir.ExprMem( - dst.ptr + m2_expr.ExprInt( - (size // 8) * 3, - dst.ptr.size - ), - size=size - ) - e.append(m2_expr.ExprAssign(ad, float_eip[:size])) - ad = ir.ExprMem( - dst.ptr + m2_expr.ExprInt( - (size // 8) * 4, - dst.ptr.size - ), - size=16 - ) - e.append(m2_expr.ExprAssign(ad, float_cs)) - ad = ir.ExprMem( - dst.ptr + m2_expr.ExprInt( - (size // 8) * 5, - dst.ptr.size - ), - size=size - ) - e.append(m2_expr.ExprAssign(ad, float_address[:size])) - ad = ir.ExprMem( - dst.ptr + m2_expr.ExprInt( - (size // 8) * 6, - dst.ptr.size - ), - size=16 - ) - e.append(m2_expr.ExprAssign(ad, float_ds)) - return e, [] - - -def fldenv(ir, instr, src): - e = [] - # Inspired from fnstenv (same TODOs / issues) - - s = instr.mode - # The behaviour in 64bit is identical to 32 bit - # This will truncate addresses - size = min(32, s) - - # Float control - ad = ir.ExprMem(src.ptr, size=16) - e.append(m2_expr.ExprAssign(float_control, ad)) - - # Status word - ad = ir.ExprMem( - src.ptr + m2_expr.ExprInt( - size // (8 * 1), - size=src.ptr.size - ), - size=16 - ) - e += [ - m2_expr.ExprAssign(x, y) for x, y in ((float_c0, ad[8:9]), - (float_c1, ad[9:10]), - (float_c2, ad[10:11]), - (float_stack_ptr, ad[11:14]), - (float_c3, ad[14:15])) - ] - - # EIP, CS, Address, DS - for offset, target in ( - (3, float_eip[:size]), - (4, float_cs), - (5, float_address[:size]), - (6, float_ds) - ): - ad = ir.ExprMem( - src.ptr + m2_expr.ExprInt( - size // ( 8 * offset), - size=src.ptr.size - ), - size=target.size - ) - e.append(m2_expr.ExprAssign(target, ad)) - - return e, [] - - -def fsub(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fsub', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fsubp(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fsub', dst, src))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fsubr(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fsub', src, dst))) - e += set_float_cs_eip(instr) - return e, [] - - -def fsubrp(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fsub', src, dst))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fmul(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fmul', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fimul(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fimul', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fdiv(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fdiv', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fdivr(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fdiv', src, dst))) - e += set_float_cs_eip(instr) - return e, [] - - -def fdivrp(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fdiv', src, dst))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fidiv(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fidiv', dst, src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fidivr(_, instr, dst, src=None): - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('fidiv', src, dst))) - e += set_float_cs_eip(instr) - return e, [] - - -def fdivp(_, instr, dst, src=None): - # Invalid emulation - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fdiv', dst, src))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def fmulp(_, instr, dst, src=None): - # Invalid emulation - dst, src = float_implicit_st0(dst, src) - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_prev(dst), m2_expr.ExprOp('fmul', dst, src))) - e += set_float_cs_eip(instr) - e += float_pop(dst) - return e, [] - - -def ftan(_, instr, src): - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('ftan', src))) - e += set_float_cs_eip(instr) - return e, [] - - -def fxch(_, instr, src): - e = [] - src = mem2double(instr, src) - e.append(m2_expr.ExprAssign(float_st0, src)) - e.append(m2_expr.ExprAssign(src, float_st0)) - e += set_float_cs_eip(instr) - return e, [] - - -def fptan(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st7, float_st6)) - e.append(m2_expr.ExprAssign(float_st6, float_st5)) - e.append(m2_expr.ExprAssign(float_st5, float_st4)) - e.append(m2_expr.ExprAssign(float_st4, float_st3)) - e.append(m2_expr.ExprAssign(float_st3, float_st2)) - e.append(m2_expr.ExprAssign(float_st2, float_st1)) - e.append(m2_expr.ExprAssign(float_st1, m2_expr.ExprOp('ftan', float_st0))) - e.append( - m2_expr.ExprAssign( - float_st0, - m2_expr.ExprOp( - 'sint_to_fp', - m2_expr.ExprInt(1, 64) - ) - ) - ) - e.append( - m2_expr.ExprAssign(float_stack_ptr, - float_stack_ptr + m2_expr.ExprInt(1, 3))) - return e, [] - - -def frndint(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('frndint', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fsin(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fsin', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fcos(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fcos', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fsincos(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st7, float_st6)) - e.append(m2_expr.ExprAssign(float_st6, float_st5)) - e.append(m2_expr.ExprAssign(float_st5, float_st4)) - e.append(m2_expr.ExprAssign(float_st4, float_st3)) - e.append(m2_expr.ExprAssign(float_st3, float_st2)) - e.append(m2_expr.ExprAssign(float_st2, float_st1)) - e.append(m2_expr.ExprAssign(float_st1, m2_expr.ExprOp('fsin', float_st0))) - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fcos', float_st0))) - e.append( - m2_expr.ExprAssign(float_stack_ptr, - float_stack_ptr + m2_expr.ExprInt(1, 3))) - return e, [] - - -def fscale(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fscale', float_st0, - float_st1))) - e += set_float_cs_eip(instr) - return e, [] - - -def f2xm1(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('f2xm1', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fchs(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fchs', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fsqrt(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fsqrt', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fabs(_, instr): - e = [] - e.append(m2_expr.ExprAssign(float_st0, m2_expr.ExprOp('fabs', float_st0))) - e += set_float_cs_eip(instr) - return e, [] - - -def fnstsw(_, instr, dst): - args = [ - # Exceptions -> 0 - m2_expr.ExprInt(0, 8), - float_c0, - float_c1, - float_c2, - float_stack_ptr, - float_c3, - # B: FPU is not busy -> 0 - m2_expr.ExprInt(0, 1)] - e = [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*args))] - return e, [] - - -def fnstcw(_, instr, dst): - e = [] - e.append(m2_expr.ExprAssign(dst, float_control)) - return e, [] - - -def fldcw(_, instr, src): - e = [] - e.append(m2_expr.ExprAssign(float_control, src)) - return e, [] - - -def fwait(_, instr): - return [], [] - - -def fcmovb(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, cf, arg1, arg2, True) - - -def fcmove(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, zf, arg1, arg2, True) - - -def fcmovbe(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, cf | zf, arg1, arg2, True) - - -def fcmovu(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, pf, arg1, arg2, True) - - -def fcmovnb(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, cf, arg1, arg2, False) - - -def fcmovne(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, zf, arg1, arg2, False) - - -def fcmovnbe(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, cf | zf, arg1, arg2, False) - - -def fcmovnu(ir, instr, arg1, arg2): - return gen_fcmov(ir, instr, pf, arg1, arg2, False) - - -def nop(_, instr, a=None): - return [], [] - - -def prefetch0(_, instr, src=None): - # see 4-198 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def prefetch1(_, instr, src=None): - # see 4-198 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def prefetch2(_, instr, src=None): - # see 4-198 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def prefetchw(_, instr, src=None): - # see 4-201 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - -def prefetchnta(_, instr, src=None): - # see 4-201 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def lfence(_, instr, src=None): - # see 3-485 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def mfence(_, instr, src=None): - # see 3-516 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def sfence(_, instr, src=None): - # see 3-356 on this documentation - # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf - return [], [] - - -def ud2(_, instr, src=None): - e = [m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt( - EXCEPT_ILLEGAL_INSN, exception_flags.size))] - return e, [] - - -def hlt(_, instr): - e = [] - except_int = EXCEPT_PRIV_INSN - e.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt(except_int, 32))) - return e, [] - - -def rdtsc(_, instr): - e = [] - e.append(m2_expr.ExprAssign(tsc, tsc + m2_expr.ExprInt(1, 64))) - e.append(m2_expr.ExprAssign(mRAX[32], tsc[:32])) - e.append(m2_expr.ExprAssign(mRDX[32], tsc[32:])) - return e, [] - - -def daa(_, instr): - e = [] - r_al = mRAX[instr.mode][:8] - - cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af - e.append(m2_expr.ExprAssign(af, cond1)) - - cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) - cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf - - cf_c1 = m2_expr.ExprCond(cond1, - cf | (cond2), - m2_expr.ExprInt(0, 1)) - new_cf = m2_expr.ExprCond(cond3, - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)) - e.append(m2_expr.ExprAssign(cf, new_cf)) - - al_c1 = m2_expr.ExprCond(cond1, - r_al + m2_expr.ExprInt(6, 8), - r_al) - - new_al = m2_expr.ExprCond(cond3, - al_c1 + m2_expr.ExprInt(0x60, 8), - al_c1) - e.append(m2_expr.ExprAssign(r_al, new_al)) - e += update_flag_znp(new_al) - return e, [] - - -def das(_, instr): - e = [] - r_al = mRAX[instr.mode][:8] - - cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af - e.append(m2_expr.ExprAssign(af, cond1)) - - cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) - cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf - - cf_c1 = m2_expr.ExprCond(cond1, - cf | (cond2), - m2_expr.ExprInt(0, 1)) - new_cf = m2_expr.ExprCond(cond3, - m2_expr.ExprInt(1, 1), - cf_c1) - e.append(m2_expr.ExprAssign(cf, new_cf)) - - al_c1 = m2_expr.ExprCond(cond1, - r_al - m2_expr.ExprInt(6, 8), - r_al) - - new_al = m2_expr.ExprCond(cond3, - al_c1 - m2_expr.ExprInt(0x60, 8), - al_c1) - e.append(m2_expr.ExprAssign(r_al, new_al)) - e += update_flag_znp(new_al) - return e, [] - - -def aam(ir, instr, src): - e = [] - assert src.is_int() - - value = int(src) - if value: - tempAL = mRAX[instr.mode][0:8] - newEAX = m2_expr.ExprCompose( - m2_expr.ExprOp("umod", tempAL, src), - m2_expr.ExprOp("udiv", tempAL, src), - mRAX[instr.mode][16:] - ) - e += [m2_expr.ExprAssign(mRAX[instr.mode], newEAX)] - e += update_flag_arith(newEAX) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - else: - e.append( - m2_expr.ExprAssign( - exception_flags, - m2_expr.ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size) - ) - ) - return e, [] - - -def aad(_, instr, src): - e = [] - tempAL = mRAX[instr.mode][0:8] - tempAH = mRAX[instr.mode][8:16] - newEAX = m2_expr.ExprCompose((tempAL + (tempAH * src)) & m2_expr.ExprInt(0xFF, 8), - m2_expr.ExprInt(0, 8), - mRAX[instr.mode][16:]) - e += [m2_expr.ExprAssign(mRAX[instr.mode], newEAX)] - e += update_flag_arith(newEAX) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - return e, [] - - -def _tpl_aaa(_, instr, op): - """Templating for aaa, aas with operation @op - @op: operation to apply - """ - e = [] - r_al = mRAX[instr.mode][:8] - r_ah = mRAX[instr.mode][8:16] - r_ax = mRAX[instr.mode][:16] - i0 = m2_expr.ExprInt(0, 1) - i1 = m2_expr.ExprInt(1, 1) - # cond: if (al & 0xf) > 9 OR af == 1 - cond = (r_al & m2_expr.ExprInt(0xf, 8)) - m2_expr.ExprInt(9, 8) - cond = ~cond.msb() & m2_expr.ExprCond(cond, i1, i0) - cond |= af & i1 - - to_add = m2_expr.ExprInt(0x106, size=r_ax.size) - if op == "-": - # Avoid ExprOp("-", A, B), should be ExprOp("+", A, ExprOp("-", B)) - first_part = r_ax - to_add - else: - first_part = m2_expr.ExprOp(op, r_ax, to_add) - new_ax = first_part & m2_expr.ExprInt(0xff0f, - size=r_ax.size) - # set AL - e.append(m2_expr.ExprAssign(r_ax, m2_expr.ExprCond(cond, new_ax, r_ax))) - e.append(m2_expr.ExprAssign(af, cond)) - e.append(m2_expr.ExprAssign(cf, cond)) - return e, [] - - -def aaa(ir, instr): - return _tpl_aaa(ir, instr, "+") - - -def aas(ir, instr): - return _tpl_aaa(ir, instr, "-") - - -def bsr_bsf(ir, instr, dst, src, op_func): - """ - IF SRC == 0 - ZF = 1 - DEST is left unchanged - ELSE - ZF = 0 - DEST = @op_func(SRC) - """ - loc_src_null, loc_src_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_src_not_null, loc_src_not_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) - - aff_dst = m2_expr.ExprAssign(ir.IRDst, loc_next_expr) - e = [m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(src, - loc_src_not_null_expr, - loc_src_null_expr))] - e_src_null = [] - e_src_null.append(m2_expr.ExprAssign(zf, m2_expr.ExprInt(1, zf.size))) - # XXX destination is undefined - e_src_null.append(aff_dst) - - e_src_not_null = [] - e_src_not_null.append(m2_expr.ExprAssign(zf, m2_expr.ExprInt(0, zf.size))) - e_src_not_null.append(m2_expr.ExprAssign(dst, op_func(src))) - e_src_not_null.append(aff_dst) - - return e, [IRBlock(ir.loc_db, loc_src_null, [AssignBlock(e_src_null, instr)]), - IRBlock(ir.loc_db, loc_src_not_null, [AssignBlock(e_src_not_null, instr)])] - - -def bsf(ir, instr, dst, src): - return bsr_bsf(ir, instr, dst, src, - lambda src: m2_expr.ExprOp("cnttrailzeros", src)) - - -def bsr(ir, instr, dst, src): - return bsr_bsf( - ir, instr, dst, src, - lambda src: m2_expr.ExprInt(src.size - 1, src.size) - m2_expr.ExprOp("cntleadzeros", src) - ) - - -def arpl(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt(1 << 7, 32))) - return e, [] - - -def ins(_, instr, size): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt(1 << 7, 32))) - return e, [] - - -def sidt(ir, instr, dst): - e = [] - if not isinstance(dst, m2_expr.ExprMem) or dst.size != 32: - raise ValueError('not exprmem 32bit instance!!') - ptr = dst.ptr - LOG_X86_SEM.warning("DEFAULT SIDT ADDRESS %s!!", dst) - e.append(m2_expr.ExprAssign(ir.ExprMem(ptr, 32), - m2_expr.ExprInt(0xe40007ff, 32))) - e.append( - m2_expr.ExprAssign(ir.ExprMem(ptr + m2_expr.ExprInt(4, ptr.size), 16), - m2_expr.ExprInt(0x8245, 16))) - return e, [] - - -def sldt(_, instr, dst): - LOG_X86_SEM.warning("DEFAULT SLDT ADDRESS %s!!", dst) - e = [m2_expr.ExprAssign(dst, m2_expr.ExprInt(0, dst.size))] - return e, [] - - -def cmovz(ir, instr, dst, src): - #return gen_cmov(ir, instr, zf, dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, True) - - -def cmovnz(ir, instr, dst, src): - #return gen_cmov(ir, instr, zf, dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, False) - - -def cmovpe(ir, instr, dst, src): - return gen_cmov(ir, instr, pf, dst, src, True) - - -def cmovnp(ir, instr, dst, src): - return gen_cmov(ir, instr, pf, dst, src, False) - - -def cmovge(ir, instr, dst, src): - #return gen_cmov(ir, instr, nf ^ of, dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, src, True) - - -def cmovg(ir, instr, dst, src): - #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, src, True) - - -def cmovl(ir, instr, dst, src): - #return gen_cmov(ir, instr, nf ^ of, dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, src, True) - - -def cmovle(ir, instr, dst, src): - #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, src, True) - - -def cmova(ir, instr, dst, src): - #return gen_cmov(ir, instr, cf | zf, dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, src, True) - - -def cmovae(ir, instr, dst, src): - #return gen_cmov(ir, instr, cf, dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, src, True) - - -def cmovbe(ir, instr, dst, src): - #return gen_cmov(ir, instr, cf | zf, dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, src, True) - - -def cmovb(ir, instr, dst, src): - #return gen_cmov(ir, instr, cf, dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, src, True) - - -def cmovo(ir, instr, dst, src): - return gen_cmov(ir, instr, of, dst, src, True) - - -def cmovno(ir, instr, dst, src): - return gen_cmov(ir, instr, of, dst, src, False) - - -def cmovs(ir, instr, dst, src): - #return gen_cmov(ir, instr, nf, dst, src, True) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, True) - - -def cmovns(ir, instr, dst, src): - #return gen_cmov(ir, instr, nf, dst, src, False) - return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, False) - - -def icebp(_, instr): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_SOFT_BP, 32))) - return e, [] -# XXX - - -def l_int(_, instr, src): - e = [] - # XXX - assert src.is_int() - value = int(src) - if value == 1: - except_int = EXCEPT_INT_1 - elif value == 3: - except_int = EXCEPT_SOFT_BP - else: - except_int = EXCEPT_INT_XX - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(except_int, 32))) - e.append(m2_expr.ExprAssign(interrupt_num, src)) - return e, [] - - -def l_sysenter(_, instr): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) - return e, [] - - -def l_syscall(_, instr): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_SYSCALL, 32))) - return e, [] - -# XXX - - -def l_out(_, instr, src1, src2): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) - return e, [] - -# XXX - - -def l_outs(_, instr, size): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) - return e, [] - -# XXX actually, xlat performs al = (ds:[e]bx + ZeroExtend(al)) - - -def xlat(ir, instr): - e = [] - ptr = mRAX[instr.mode][0:8].zeroExtend(mRBX[instr.mode].size) - src = ir.ExprMem(mRBX[instr.mode] + ptr, 8) - e.append(m2_expr.ExprAssign(mRAX[instr.mode][0:8], src)) - return e, [] - - -def cpuid(_, instr): - e = [] - e.append( - m2_expr.ExprAssign(mRAX[instr.mode], - m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(0, instr.mode)))) - e.append( - m2_expr.ExprAssign(mRBX[instr.mode], - m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(1, instr.mode)))) - e.append( - m2_expr.ExprAssign(mRCX[instr.mode], - m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(2, instr.mode)))) - e.append( - m2_expr.ExprAssign(mRDX[instr.mode], - m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(3, instr.mode)))) - return e, [] - - -def bittest_get(ir, instr, src, index): - index = index.zeroExtend(src.size) - if isinstance(src, m2_expr.ExprMem): - b_mask = {16: 4, 32: 5, 64: 6} - b_decal = {16: 1, 32: 3, 64: 7} - ptr = src.ptr - segm = is_mem_segm(src) - if segm: - ptr = ptr.args[1] - - off_bit = index.zeroExtend( - src.size) & m2_expr.ExprInt((1 << b_mask[src.size]) - 1, - src.size) - off_byte = ((index.zeroExtend(ptr.size) >> m2_expr.ExprInt(3, ptr.size)) & - m2_expr.ExprInt(((1 << src.size) - 1) ^ b_decal[src.size], ptr.size)) - - addr = ptr + off_byte - if segm: - addr = ir.gen_segm_expr(src.ptr.args[0], addr) - - d = ir.ExprMem(addr, src.size) - else: - off_bit = m2_expr.ExprOp( - '&', index, m2_expr.ExprInt(src.size - 1, src.size)) - d = src - return d, off_bit - - -def bt(ir, instr, src, index): - e = [] - index = index.zeroExtend(src.size) - d, off_bit = bittest_get(ir, instr, src, index) - d = d >> off_bit - e.append(m2_expr.ExprAssign(cf, d[:1])) - return e, [] - - -def btc(ir, instr, src, index): - e = [] - d, off_bit = bittest_get(ir, instr, src, index) - e.append(m2_expr.ExprAssign(cf, (d >> off_bit)[:1])) - - m = m2_expr.ExprInt(1, src.size) << off_bit - e.append(m2_expr.ExprAssign(d, d ^ m)) - - return e, [] - - -def bts(ir, instr, src, index): - e = [] - d, off_bit = bittest_get(ir, instr, src, index) - e.append(m2_expr.ExprAssign(cf, (d >> off_bit)[:1])) - m = m2_expr.ExprInt(1, src.size) << off_bit - e.append(m2_expr.ExprAssign(d, d | m)) - - return e, [] - - -def btr(ir, instr, src, index): - e = [] - d, off_bit = bittest_get(ir, instr, src, index) - e.append(m2_expr.ExprAssign(cf, (d >> off_bit)[:1])) - m = ~(m2_expr.ExprInt(1, src.size) << off_bit) - e.append(m2_expr.ExprAssign(d, d & m)) - - return e, [] - - -def into(_, instr): - return [], [] - - -def l_in(_, instr, src1, src2): - e = [] - e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) - return e, [] - - -@sbuild.parse -def cmpxchg(arg1, arg2): - accumulator = mRAX[instr.v_opmode()][:arg1.size] - if (accumulator - arg1): - zf = i1(0) - accumulator = arg1 - else: - zf = i1(1) - arg1 = arg2 - - -@sbuild.parse -def cmpxchg8b(arg1): - accumulator = {mRAX[32], mRDX[32]} - if accumulator - arg1: - zf = i1(0) - mRAX[32] = arg1[:32] - mRDX[32] = arg1[32:] - else: - zf = i1(1) - arg1 = {mRBX[32], mRCX[32]} - - -@sbuild.parse -def cmpxchg16b(arg1): - accumulator = {mRAX[64], mRDX[64]} - if accumulator - arg1: - zf = i1(0) - mRAX[64] = arg1[:64] - mRDX[64] = arg1[64:] - else: - zf = i1(1) - arg1 = {mRBX[64], mRCX[64]} - - -def lds(ir, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, ir.ExprMem(src.ptr, size=dst.size))) - DS_value = ir.ExprMem(src.ptr + m2_expr.ExprInt(dst.size // 8, src.ptr.size), - size=16) - e.append(m2_expr.ExprAssign(DS, DS_value)) - return e, [] - - -def les(ir, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, ir.ExprMem(src.ptr, size=dst.size))) - ES_value = ir.ExprMem(src.ptr + m2_expr.ExprInt(dst.size // 8, src.ptr.size), - size=16) - e.append(m2_expr.ExprAssign(ES, ES_value)) - return e, [] - - -def lss(ir, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, ir.ExprMem(src.ptr, size=dst.size))) - SS_value = ir.ExprMem(src.ptr + m2_expr.ExprInt(dst.size // 8, src.ptr.size), - size=16) - e.append(m2_expr.ExprAssign(SS, SS_value)) - return e, [] - - -def lfs(ir, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, ir.ExprMem(src.ptr, size=dst.size))) - FS_value = ir.ExprMem(src.ptr + m2_expr.ExprInt(dst.size // 8, src.ptr.size), - size=16) - e.append(m2_expr.ExprAssign(FS, FS_value)) - return e, [] - - -def lgs(ir, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, ir.ExprMem(src.ptr, size=dst.size))) - GS_value = ir.ExprMem(src.ptr + m2_expr.ExprInt(dst.size // 8, src.ptr.size), - size=16) - e.append(m2_expr.ExprAssign(GS, GS_value)) - return e, [] - - -def lahf(_, instr): - e = [] - args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, - m2_expr.ExprInt(0, 1), zf, nf] - e.append( - m2_expr.ExprAssign(mRAX[instr.mode][8:16], m2_expr.ExprCompose(*args))) - return e, [] - - -def sahf(_, instr): - tmp = mRAX[instr.mode][8:16] - e = [] - e.append(m2_expr.ExprAssign(cf, tmp[0:1])) - e.append(m2_expr.ExprAssign(pf, tmp[2:3])) - e.append(m2_expr.ExprAssign(af, tmp[4:5])) - e.append(m2_expr.ExprAssign(zf, tmp[6:7])) - e.append(m2_expr.ExprAssign(nf, tmp[7:8])) - return e, [] - - -def lar(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('access_segment', src))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp('access_segment_ok', src))) - return e, [] - - -def lsl(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('load_segment_limit', src))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp('load_segment_limit_ok', src))) - return e, [] - - -def fclex(_, instr): - # XXX TODO - return [], [] - - -def fnclex(_, instr): - # XXX TODO - return [], [] - - -def l_str(_, instr, dst): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('load_tr_segment_selector', - m2_expr.ExprInt(0, 32)))) - return e, [] - - -def movd(_, instr, dst, src): - e = [] - if dst in regs_mm_expr: - e.append(m2_expr.ExprAssign( - dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 32)))) - elif dst in regs_xmm_expr: - e.append(m2_expr.ExprAssign( - dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) - else: - e.append(m2_expr.ExprAssign(dst, src[:32])) - return e, [] - - -def movdqu(_, instr, dst, src): - # XXX TODO alignment check - return [m2_expr.ExprAssign(dst, src)], [] - - -def movapd(_, instr, dst, src): - # XXX TODO alignment check - return [m2_expr.ExprAssign(dst, src)], [] - - -def andps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('&', dst, src))) - return e, [] - - -def andnps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('&', dst ^ dst.mask, src))) - return e, [] - - -def orps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('|', dst, src))) - return e, [] - - -def xorps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprOp('^', dst, src))) - return e, [] - - -def rdmsr(ir, instr): - e = [m2_expr.ExprAssign(exception_flags,m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))] - return e, [] - - -def wrmsr(ir, instr): - e = [m2_expr.ExprAssign(exception_flags,m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))] - return e, [] - -# MMX/SSE/AVX operations -# - -def vec_op_clip(op, size, callback=None): - """ - Generate simd operations - @op: the operator - @size: size of an element - """ - def vec_op_clip_instr(ir, instr, dst, src): - if op == '-': - result = dst[:size] - src[:size] - else: - result = m2_expr.ExprOp(op, dst[:size], src[:size]) - if callback is not None: - result = callback(result) - return [m2_expr.ExprAssign(dst[:size], result)], [] - return vec_op_clip_instr - -# Generic vertical operation - - -def vec_vertical_sem(op, elt_size, reg_size, dst, src, apply_on_output): - assert reg_size % elt_size == 0 - n = reg_size // elt_size - if op == '-': - ops = [ - apply_on_output((dst[i * elt_size:(i + 1) * elt_size] - - src[i * elt_size:(i + 1) * elt_size])) - for i in range(0, n) - ] - else: - ops = [ - apply_on_output(m2_expr.ExprOp(op, dst[i * elt_size:(i + 1) * elt_size], - src[i * elt_size:(i + 1) * elt_size])) - for i in range(0, n) - ] - - return m2_expr.ExprCompose(*ops) - - -def __vec_vertical_instr_gen(op, elt_size, sem, apply_on_output): - def vec_instr(ir, instr, dst, src): - e = [] - if isinstance(src, m2_expr.ExprMem): - src = ir.ExprMem(src.ptr, dst.size) - reg_size = dst.size - e.append(m2_expr.ExprAssign(dst, sem(op, elt_size, reg_size, dst, src, - apply_on_output))) - return e, [] - return vec_instr - - -def vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x): - return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem, - apply_on_output) - - -def _keep_mul_high(expr, signed=False): - assert expr.is_op("*") and len(expr.args) == 2 - - if signed: - arg1 = expr.args[0].signExtend(expr.size * 2) - arg2 = expr.args[1].signExtend(expr.size * 2) - else: - arg1 = expr.args[0].zeroExtend(expr.size * 2) - arg2 = expr.args[1].zeroExtend(expr.size * 2) - return m2_expr.ExprOp("*", arg1, arg2)[expr.size:] - -# Op, signed => associated comparison -_min_max_func = { - ("min", False): m2_expr.expr_is_unsigned_lower, - ("min", True): m2_expr.expr_is_signed_lower, - ("max", False): m2_expr.expr_is_unsigned_greater, - ("max", True): m2_expr.expr_is_signed_greater, -} -def _min_max(expr, signed): - assert (expr.is_op("min") or expr.is_op("max")) and len(expr.args) == 2 - return m2_expr.ExprCond( - _min_max_func[(expr.op, signed)](expr.args[1], expr.args[0]), - expr.args[1], - expr.args[0], - ) - -def _float_min_max(expr): - assert (expr.is_op("fmin") or expr.is_op("fmax")) and len(expr.args) == 2 - src1 = expr.args[0] - src2 = expr.args[1] - if expr.is_op("fmin"): - comp = m2_expr.expr_is_float_lower(src1, src2) - elif expr.is_op("fmax"): - comp = m2_expr.expr_is_float_lower(src2, src1) - - # x86 documentation (for MIN): - # IF ((SRC1 = 0.0) and (SRC2 = 0.0)) THEN DEST <-SRC2; - # ELSE IF (SRC1 = SNaN) THEN DEST <-SRC2; FI; - # ELSE IF (SRC2 = SNaN) THEN DEST <-SRC2; FI; - # ELSE IF (SRC1 < SRC2) THEN DEST <-SRC1; - # ELSE DEST<-SRC2; - # - # But this includes the NaN output of "SRC1 < SRC2" - # Associated text is more detailed, and this is the version impl here - return m2_expr.ExprCond( - m2_expr.expr_is_sNaN(src2), src2, - m2_expr.ExprCond( - m2_expr.expr_is_NaN(src2) | m2_expr.expr_is_NaN(src1), src2, - m2_expr.ExprCond(comp, src1, src2) - ) - ) - - -# Integer arithmetic -# - -# Additions -# - -# SSE -paddb = vec_vertical_instr('+', 8) -paddw = vec_vertical_instr('+', 16) -paddd = vec_vertical_instr('+', 32) -paddq = vec_vertical_instr('+', 64) - -# Substractions -# - -# SSE -psubb = vec_vertical_instr('-', 8) -psubw = vec_vertical_instr('-', 16) -psubd = vec_vertical_instr('-', 32) -psubq = vec_vertical_instr('-', 64) - -# Multiplications -# - -# SSE -pmullb = vec_vertical_instr('*', 8) -pmullw = vec_vertical_instr('*', 16) -pmulld = vec_vertical_instr('*', 32) -pmullq = vec_vertical_instr('*', 64) -pmulhub = vec_vertical_instr('*', 8, _keep_mul_high) -pmulhuw = vec_vertical_instr('*', 16, _keep_mul_high) -pmulhud = vec_vertical_instr('*', 32, _keep_mul_high) -pmulhuq = vec_vertical_instr('*', 64, _keep_mul_high) -pmulhb = vec_vertical_instr('*', 8, lambda x: _keep_mul_high(x, signed=True)) -pmulhw = vec_vertical_instr('*', 16, lambda x: _keep_mul_high(x, signed=True)) -pmulhd = vec_vertical_instr('*', 32, lambda x: _keep_mul_high(x, signed=True)) -pmulhq = vec_vertical_instr('*', 64, lambda x: _keep_mul_high(x, signed=True)) - -def pmuludq(ir, instr, dst, src): - e = [] - if dst.size == 64: - e.append(m2_expr.ExprAssign( - dst, - src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) - )) - elif dst.size == 128: - e.append(m2_expr.ExprAssign( - dst[:64], - src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) - )) - e.append(m2_expr.ExprAssign( - dst[64:], - src[64:96].zeroExtend(64) * dst[64:96].zeroExtend(64) - )) - else: - raise RuntimeError("Unsupported size %d" % dst.size) - return e, [] - -# Mix -# - -# SSE -def pmaddwd(ir, instr, dst, src): - sizedst = 32 - sizesrc = 16 - out = [] - for start in range(0, dst.size, sizedst): - base = start - mul1 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) - base += sizesrc - mul2 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) - out.append(mul1 + mul2) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def _absolute(expr): - """Return abs(@expr)""" - signed = expr.msb() - value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) - return m2_expr.ExprCond(signed, value_unsigned, expr) - - -def psadbw(ir, instr, dst, src): - sizedst = 16 - sizesrc = 8 - out_dst = [] - for start in range(0, dst.size, 64): - out = [] - for src_start in range(0, 64, sizesrc): - beg = start + src_start - end = beg + sizesrc - # Not clear in the doc equations, but in the text, src and dst are: - # "8 unsigned byte integers" - out.append(_absolute(dst[beg: end].zeroExtend(sizedst) - src[beg: end].zeroExtend(sizedst))) - out_dst.append(m2_expr.ExprOp("+", *out)) - out_dst.append(m2_expr.ExprInt(0, 64 - sizedst)) - - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out_dst))], [] - -def _average(expr): - assert expr.is_op("avg") and len(expr.args) == 2 - - arg1 = expr.args[0].zeroExtend(expr.size * 2) - arg2 = expr.args[1].zeroExtend(expr.size * 2) - one = m2_expr.ExprInt(1, arg1.size) - # avg(unsigned) = (a + b + 1) >> 1, addition being at least on one more bit - return ((arg1 + arg2 + one) >> one)[:expr.size] - -pavgb = vec_vertical_instr('avg', 8, _average) -pavgw = vec_vertical_instr('avg', 16, _average) - -# Comparisons -# - -# SSE -pminsw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=True)) -pminub = vec_vertical_instr('min', 8, lambda x: _min_max(x, signed=False)) -pminuw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=False)) -pminud = vec_vertical_instr('min', 32, lambda x: _min_max(x, signed=False)) -pmaxub = vec_vertical_instr('max', 8, lambda x: _min_max(x, signed=False)) -pmaxuw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=False)) -pmaxud = vec_vertical_instr('max', 32, lambda x: _min_max(x, signed=False)) -pmaxsw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=True)) - -# Floating-point arithmetic -# - -# SSE -addss = vec_op_clip('fadd', 32) -addsd = vec_op_clip('fadd', 64) -addps = vec_vertical_instr('fadd', 32) -addpd = vec_vertical_instr('fadd', 64) -subss = vec_op_clip('fsub', 32) -subsd = vec_op_clip('fsub', 64) -subps = vec_vertical_instr('fsub', 32) -subpd = vec_vertical_instr('fsub', 64) -mulss = vec_op_clip('fmul', 32) -mulsd = vec_op_clip('fmul', 64) -mulps = vec_vertical_instr('fmul', 32) -mulpd = vec_vertical_instr('fmul', 64) -divss = vec_op_clip('fdiv', 32) -divsd = vec_op_clip('fdiv', 64) -divps = vec_vertical_instr('fdiv', 32) -divpd = vec_vertical_instr('fdiv', 64) - -# Comparisons (floating-point) - -minps = vec_vertical_instr('fmin', 32, _float_min_max) -minpd = vec_vertical_instr('fmin', 64, _float_min_max) -minss = vec_op_clip('fmin', 32, _float_min_max) -minsd = vec_op_clip('fmin', 64, _float_min_max) -maxps = vec_vertical_instr('fmax', 32, _float_min_max) -maxpd = vec_vertical_instr('fmax', 64, _float_min_max) -maxss = vec_op_clip('fmax', 32, _float_min_max) -maxsd = vec_op_clip('fmax', 64, _float_min_max) - -def _float_compare_to_mask(expr): - if expr.op == 'unord': - to_ext = m2_expr.expr_is_NaN(expr.args[0]) | m2_expr.expr_is_NaN(expr.args[1]) - elif expr.op == 'ord': - to_ext = ~m2_expr.expr_is_NaN(expr.args[0]) & ~m2_expr.expr_is_NaN(expr.args[1]) - else: - if expr.op == '==fu': - to_ext = m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) - on_NaN = m2_expr.ExprInt(0, 1) - elif expr.op == '<fu': - to_ext = m2_expr.expr_is_float_lower(expr.args[0], expr.args[1]) - on_NaN = m2_expr.ExprInt(0, 1) - elif expr.op == '<=fu': - to_ext = (m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) | - m2_expr.expr_is_float_lower(expr.args[0], expr.args[1])) - on_NaN = m2_expr.ExprInt(0, 1) - elif expr.op == '!=fu': - to_ext = ~m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) - on_NaN = m2_expr.ExprInt(1, 1) - elif expr.op == '!<fu': - to_ext = ~m2_expr.expr_is_float_lower(expr.args[0], expr.args[1]) - on_NaN = m2_expr.ExprInt(1, 1) - elif expr.op == '!<=fu': - to_ext = ~(m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) | - m2_expr.expr_is_float_lower(expr.args[0], expr.args[1])) - on_NaN = m2_expr.ExprInt(1, 1) - - to_ext = m2_expr.ExprCond( - m2_expr.expr_is_NaN(expr.args[0]) | m2_expr.expr_is_NaN(expr.args[1]), - on_NaN, - to_ext - ) - return to_ext.signExtend(expr.size) - -cmpeqps = vec_vertical_instr('==fu', 32, lambda x: _float_compare_to_mask(x)) -cmpeqpd = vec_vertical_instr('==fu', 64, lambda x: _float_compare_to_mask(x)) -cmpeqss = vec_op_clip('==fu', 32, lambda x: _float_compare_to_mask(x)) -cmpeqsd = vec_op_clip('==fu', 64, lambda x: _float_compare_to_mask(x)) -cmpltps = vec_vertical_instr('<fu', 32, lambda x: _float_compare_to_mask(x)) -cmpltpd = vec_vertical_instr('<fu', 64, lambda x: _float_compare_to_mask(x)) -cmpltss = vec_op_clip('<fu', 32, lambda x: _float_compare_to_mask(x)) -cmpltsd = vec_op_clip('<fu', 64, lambda x: _float_compare_to_mask(x)) -cmpleps = vec_vertical_instr('<=fu', 32, lambda x: _float_compare_to_mask(x)) -cmplepd = vec_vertical_instr('<=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpless = vec_op_clip('<=fu', 32, lambda x: _float_compare_to_mask(x)) -cmplesd = vec_op_clip('<=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpunordps = vec_vertical_instr('unord', 32, lambda x: _float_compare_to_mask(x)) -cmpunordpd = vec_vertical_instr('unord', 64, lambda x: _float_compare_to_mask(x)) -cmpunordss = vec_op_clip('unord', 32, lambda x: _float_compare_to_mask(x)) -cmpunordsd = vec_op_clip('unord', 64, lambda x: _float_compare_to_mask(x)) -cmpneqps = vec_vertical_instr('!=fu', 32, lambda x: _float_compare_to_mask(x)) -cmpneqpd = vec_vertical_instr('!=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpneqss = vec_op_clip('!=fu', 32, lambda x: _float_compare_to_mask(x)) -cmpneqsd = vec_op_clip('!=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpnltps = vec_vertical_instr('!<fu', 32, lambda x: _float_compare_to_mask(x)) -cmpnltpd = vec_vertical_instr('!<fu', 64, lambda x: _float_compare_to_mask(x)) -cmpnltss = vec_op_clip('!<fu', 32, lambda x: _float_compare_to_mask(x)) -cmpnltsd = vec_op_clip('!<fu', 64, lambda x: _float_compare_to_mask(x)) -cmpnleps = vec_vertical_instr('!<=fu', 32, lambda x: _float_compare_to_mask(x)) -cmpnlepd = vec_vertical_instr('!<=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpnless = vec_op_clip('!<=fu', 32, lambda x: _float_compare_to_mask(x)) -cmpnlesd = vec_op_clip('!<=fu', 64, lambda x: _float_compare_to_mask(x)) -cmpordps = vec_vertical_instr('ord', 32, lambda x: _float_compare_to_mask(x)) -cmpordpd = vec_vertical_instr('ord', 64, lambda x: _float_compare_to_mask(x)) -cmpordss = vec_op_clip('ord', 32, lambda x: _float_compare_to_mask(x)) -cmpordsd = vec_op_clip('ord', 64, lambda x: _float_compare_to_mask(x)) - -# Logical (floating-point) -# - -# MMX/SSE/AVX - - -def pand(_, instr, dst, src): - e = [] - result = dst & src - # No flag assigned - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def pandn(_, instr, dst, src): - e = [] - result = (dst ^ dst.mask) & src - # No flag assigned - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def por(_, instr, dst, src): - e = [] - result = dst | src - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - - -def cvtdq2pd(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign( - dst[:64], - m2_expr.ExprOp( - 'sint_to_fp', - src[:32].signExtend(64) - ) - ) - ) - e.append( - m2_expr.ExprAssign( - dst[64:128], - m2_expr.ExprOp( - 'sint_to_fp', - src[32:64].signExtend(64) - ) - ) - ) - return e, [] - - -def cvtdq2ps(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('sint_to_fp', src[32:64]))) - e.append( - m2_expr.ExprAssign(dst[64:96], m2_expr.ExprOp('sint_to_fp', src[64:96]))) - e.append( - m2_expr.ExprAssign(dst[96:128], m2_expr.ExprOp('sint_to_fp', src[96:128]))) - return e, [] - - -def cvtpd2dq(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) - e.append(m2_expr.ExprAssign(dst[64:128], m2_expr.ExprInt(0, 64))) - return e, [] - - -def cvtpd2pi(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) - return e, [] - - -def cvtpd2ps(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('fpconvert_fp32', src[64:128]))) - e.append(m2_expr.ExprAssign(dst[64:128], m2_expr.ExprInt(0, 64))) - return e, [] - - -def cvtpi2pd(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign( - dst[:64], - m2_expr.ExprOp( - 'sint_to_fp', - src[:32].signExtend(64) - ) - ) - ) - e.append( - m2_expr.ExprAssign( - dst[64:128], - m2_expr.ExprOp( - 'sint_to_fp', - src[32:64].signExtend(64)) - ) - ) - return e, [] - - -def cvtpi2ps(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('sint_to_fp', src[32:64]))) - return e, [] - - -def cvtps2dq(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) - e.append( - m2_expr.ExprAssign(dst[64:96], m2_expr.ExprOp('fp_to_sint32', src[64:96]))) - e.append( - m2_expr.ExprAssign(dst[96:128], m2_expr.ExprOp('fp_to_sint32', src[96:128]))) - return e, [] - - -def cvtps2pd(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) - e.append( - m2_expr.ExprAssign(dst[64:128], m2_expr.ExprOp('fpconvert_fp64', src[32:64]))) - return e, [] - - -def cvtps2pi(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) - e.append( - m2_expr.ExprAssign(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) - return e, [] - - -def cvtsd2si(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) - return e, [] - - -def cvtsd2ss(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) - return e, [] - - -def cvtsi2sd(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign( - dst[:64], - m2_expr.ExprOp( - 'sint_to_fp', - src[:32].signExtend(64) - ) - ) - ) - return e, [] - - -def cvtsi2ss(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) - return e, [] - - -def cvtss2sd(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) - return e, [] - - -def cvtss2si(_, instr, dst, src): - e = [] - e.append( - m2_expr.ExprAssign(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) - return e, [] - - -def _cvtt_tpl(dst, src, numbers, double): - e = [] - for i in numbers: - # For CVTT*D2* (Convert with Truncation ... Double-Precision) to work, - # a first conversion fp64 -> fp32 is needed - if double: - tmp_src = m2_expr.ExprOp('fpconvert_fp32', src[i*64:i*64 + 64]) - else: - tmp_src = src[i*32:i*32 + 32] - - e.append(m2_expr.ExprAssign( - dst[i*32:i*32 + 32], - m2_expr.ExprOp('fp_to_sint32', m2_expr.ExprOp( - 'fpround_towardszero', - tmp_src - )))) - return e - -def cvttpd2pi(_, instr, dst, src): - return _cvtt_tpl(dst, src, [0, 1], double=True), [] - -def cvttpd2dq(_, instr, dst, src): - e = _cvtt_tpl(dst, src, [0, 1], double=True) - e.append(m2_expr.ExprAssign(dst[64:128], m2_expr.ExprInt(0, 64))) - return e, [] - -def cvttsd2si(_, instr, dst, src): - return _cvtt_tpl(dst, src, [0], double=True), [] - -def cvttps2dq(_, instr, dst, src): - return _cvtt_tpl(dst, src, [0, 1, 2, 3], double=False), [] - -def cvttps2pi(_, instr, dst, src): - return _cvtt_tpl(dst, src, [0, 1], double=False), [] - -def cvttss2si(_, instr, dst, src): - return _cvtt_tpl(dst, src, [0], double=False), [] - -def movss(_, instr, dst, src): - e = [] - if not isinstance(dst, m2_expr.ExprMem) and not isinstance(src, m2_expr.ExprMem): - # Source and Destination xmm - e.append(m2_expr.ExprAssign(dst[:32], src[:32])) - elif not isinstance(src, m2_expr.ExprMem) and isinstance(dst, m2_expr.ExprMem): - # Source XMM Destination Mem - e.append(m2_expr.ExprAssign(dst, src[:32])) - else: - # Source Mem Destination XMM - e.append(m2_expr.ExprAssign( - dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) - return e, [] - - -def ucomiss(_, instr, src1, src2): - e = [] - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp( - 'ucomiss_zf', src1[:32], src2[:32]))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprOp( - 'ucomiss_pf', src1[:32], src2[:32]))) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprOp( - 'ucomiss_cf', src1[:32], src2[:32]))) - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprInt(0, 1))) - - return e, [] - -def ucomisd(_, instr, src1, src2): - e = [] - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprOp( - 'ucomisd_zf', src1[:64], src2[:64]))) - e.append(m2_expr.ExprAssign(pf, m2_expr.ExprOp( - 'ucomisd_pf', src1[:64], src2[:64]))) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprOp( - 'ucomisd_cf', src1[:64], src2[:64]))) - - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(af, m2_expr.ExprInt(0, 1))) - e.append(m2_expr.ExprAssign(nf, m2_expr.ExprInt(0, 1))) - - return e, [] - -def blsi(_, instr, dst, src): - e = [] - - arg1 = m2_expr.ExprInt(0, src.size) - neg_src = arg1 - src - result = neg_src & src - - e += update_flag_zf(result) - e += update_flag_nf(result) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(src, - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)))) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def andn(_, instr, dst, src1, src2): - e = [] - - arg1 = m2_expr.ExprInt(0, src1.size) - neg_src1 = arg1 - src1 - result = neg_src1 & src2 - - e += update_flag_zf(result) - e += update_flag_nf(result) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprInt(0, cf.size))) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def bextr(_, instr, dst, src1, src2): - e = [] - - # TODO: change zero extension to 512 bits when AVX is supported - start = (src2 & m2_expr.ExprInt(0xFF, src2.size)).zeroExtend(256) - length = ((src2 & m2_expr.ExprInt(0xFF00, src2.size)) >> m2_expr.ExprInt(8, src2.size)).zeroExtend(256) - - tmp = src1.zeroExtend(256) >> start - mask = m2_expr.ExprInt(0, 256).mask >> (m2_expr.ExprInt(256, 256) - length) - - tmp = tmp & mask - result = tmp[:dst.size] - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def blsmsk(_, instr, dst, src): - e = [] - - tmp = src - m2_expr.ExprInt(1, src.size) - result = src ^ tmp - - e += update_flag_nf(result) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - e.append(m2_expr.ExprAssign(zf, m2_expr.ExprInt(0, zf.size))) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(src, - m2_expr.ExprInt(0, 1), - m2_expr.ExprInt(1, 1)))) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def blsr(_, instr, dst, src): - e = [] - - tmp = src - m2_expr.ExprInt(1, src.size) - result = tmp & src - - e += update_flag_zf(result) - e += update_flag_nf(result) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(src, - m2_expr.ExprInt(0, 1), - m2_expr.ExprInt(1, 1)))) - - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def tzcnt(ir, instr, dst, src): - e = [] - - operand_size = m2_expr.ExprInt(dst.size, dst.size) - - result = m2_expr.ExprCond(src, m2_expr.ExprOp("cnttrailzeros", src), operand_size) - - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(m2_expr.ExprOp("FLAG_EQ_CMP", result, operand_size), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)))) - - e += update_flag_zf(result) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def bzhi(_, instr, dst, src1, src2): - e = [] - - operand_size = m2_expr.ExprInt(dst.size, dst.size) - index = src2[:7].zeroExtend(dst.size) - mask = m2_expr.ExprInt(0, dst.size).mask >> (operand_size - - index - - m2_expr.ExprInt(1, dst.size)) - - result = m2_expr.ExprCond(m2_expr.ExprOp("FLAG_SIGN_SUB", index, operand_size), - src1 & mask, src1) - - - operand_size_dec = operand_size - m2_expr.ExprInt(1, dst.size) - e.append(m2_expr.ExprAssign(cf, m2_expr.ExprCond(m2_expr.ExprOp("FLAG_SIGN_SUB", operand_size_dec, index), - m2_expr.ExprInt(1, 1), - m2_expr.ExprInt(0, 1)))) - - e += update_flag_zf(result) - e += update_flag_nf(result) - e.append(m2_expr.ExprAssign(of, m2_expr.ExprInt(0, of.size))) - e.append(m2_expr.ExprAssign(dst, result)) - return e, [] - -def pshufb(_, instr, dst, src): - e = [] - if dst.size == 64: - bit_l = 3 - elif dst.size == 128: - bit_l = 4 - else: - raise NotImplementedError("bad size") - for i in range(0, src.size, 8): - index = src[ - i:i + bit_l].zeroExtend(dst.size) << m2_expr.ExprInt(3, dst.size) - value = (dst >> index)[:8] - e.append(m2_expr.ExprAssign(dst[i:i + 8], - m2_expr.ExprCond(src[i + 7:i + 8], - m2_expr.ExprInt(0, 8), - value))) - return e, [] - - -def pshufd(_, instr, dst, src, imm): - control = int(imm) - out = [] - for i in range(4): - shift = ((control >> (i * 2)) & 3) * 32 - # shift is 2 bits long, expr.size is 128 - # => shift + 32 <= src.size - out.append(src[shift: shift + 32]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def pshuflw(_, instr, dst, src, imm): - control = int(imm) - out = [] - for i in range(4): - shift = ((control >> (i * 2)) & 3) * 16 - out.append(src[shift: shift + 16]) - out.append(src[64:]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def pshufhw(_, instr, dst, src, imm): - control = int(imm) - out = [src[:64]] - for i in range(4): - shift = ((control >> (i * 2)) & 3) * 16 - out.append(src[shift + 64: shift + 16 + 64]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def ps_rl_ll(ir, instr, dst, src, op, size): - mask = {16: 0xF, - 32: 0x1F, - 64: 0x3F}[size] - mask = m2_expr.ExprInt(mask, dst.size) - - # Saturate the counter to 2**size - count = src.zeroExtend(dst.size) - count = m2_expr.ExprCond(count & expr_simp(~mask), - m2_expr.ExprInt(size, dst.size), # saturation - count, # count < 2**size - ) - count = count[:size] - if src.is_int(): - count = expr_simp(count) - - out = [] - for i in range(0, dst.size, size): - out.append(m2_expr.ExprOp(op, dst[i:i + size], count)) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def psrlw(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, ">>", 16) - - -def psrld(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, ">>", 32) - - -def psrlq(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, ">>", 64) - - -def psllw(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, "<<", 16) - - -def pslld(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, "<<", 32) - - -def psllq(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, "<<", 64) - - -def psraw(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, "a>>", 16) - - -def psrad(ir, instr, dst, src): - return ps_rl_ll(ir, instr, dst, src, "a>>", 32) - - -def pslldq(_, instr, dst, src): - assert src.is_int() - e = [] - count = int(src) - if count > 15: - return [m2_expr.ExprAssign(dst, m2_expr.ExprInt(0, dst.size))], [] - else: - return [m2_expr.ExprAssign(dst, dst << m2_expr.ExprInt(8 * count, dst.size))], [] - - -def psrldq(_, instr, dst, src): - assert src.is_int() - count = int(src) - if count > 15: - return [m2_expr.ExprAssign(dst, m2_expr.ExprInt(0, dst.size))], [] - else: - return [m2_expr.ExprAssign(dst, dst >> m2_expr.ExprInt(8 * count, dst.size))], [] - - -def iret(ir, instr): - """IRET implementation - XXX: only support "no-privilege change" - """ - size = instr.v_opmode() - exprs, _ = retf(ir, instr, m2_expr.ExprInt(size // 8, size=size)) - tmp = mRSP[instr.mode][:size] + m2_expr.ExprInt((2 * size) // 8, size=size) - exprs += _tpl_eflags(tmp) - return exprs, [] - - -def pcmpeq(_, instr, dst, src, size): - e = [] - for i in range(0, dst.size, size): - test = m2_expr.expr_is_equal(dst[i:i + size], src[i:i + size]) - e.append(m2_expr.ExprAssign(dst[i:i + size], - m2_expr.ExprCond(test, - m2_expr.ExprInt(-1, size), - m2_expr.ExprInt(0, size)))) - return e, [] - - -def pcmpgt(_, instr, dst, src, size): - e = [] - for i in range(0, dst.size, size): - test = m2_expr.expr_is_signed_greater(dst[i:i + size], src[i:i + size]) - e.append(m2_expr.ExprAssign(dst[i:i + size], - m2_expr.ExprCond(test, - m2_expr.ExprInt(-1, size), - m2_expr.ExprInt(0, size)))) - return e, [] - - -def pcmpeqb(ir, instr, dst, src): - return pcmpeq(ir, instr, dst, src, 8) - -def pcmpeqw(ir, instr, dst, src): - return pcmpeq(ir, instr, dst, src, 16) - -def pcmpeqd(ir, instr, dst, src): - return pcmpeq(ir, instr, dst, src, 32) - -def pcmpeqq(ir, instr, dst, src): - return pcmpeq(ir, instr, dst, src, 64) - - - - -def pcmpgtb(ir, instr, dst, src): - return pcmpgt(ir, instr, dst, src, 8) - -def pcmpgtw(ir, instr, dst, src): - return pcmpgt(ir, instr, dst, src, 16) - -def pcmpgtd(ir, instr, dst, src): - return pcmpgt(ir, instr, dst, src, 32) - -def pcmpgtq(ir, instr, dst, src): - return pcmpgt(ir, instr, dst, src, 64) - - - -def punpck(_, instr, dst, src, size, off): - e = [] - slices = [] - for i in range(dst.size // (2 * size)): - slices.append(dst[size * i + off: size * i + off + size]) - slices.append(src[size * i + off: size * i + off + size]) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*slices))) - return e, [] - - -def punpckhbw(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 8, dst.size // 2) - - -def punpckhwd(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 16, dst.size // 2) - - -def punpckhdq(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 32, dst.size // 2) - - -def punpckhqdq(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 64, dst.size // 2) - - -def punpcklbw(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 8, 0) - - -def punpcklwd(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 16, 0) - - -def punpckldq(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 32, 0) - - -def punpcklqdq(ir, instr, dst, src): - return punpck(ir, instr, dst, src, 64, 0) - - -def pinsr(_, instr, dst, src, imm, size): - e = [] - - mask = {8: 0xF, - 16: 0x7, - 32: 0x3, - 64: 0x1}[size] - - sel = (int(imm) & mask) * size - e.append(m2_expr.ExprAssign(dst[sel:sel + size], src[:size])) - - return e, [] - - -def pinsrb(ir, instr, dst, src, imm): - return pinsr(ir, instr, dst, src, imm, 8) - - -def pinsrw(ir, instr, dst, src, imm): - return pinsr(ir, instr, dst, src, imm, 16) - - -def pinsrd(ir, instr, dst, src, imm): - return pinsr(ir, instr, dst, src, imm, 32) - - -def pinsrq(ir, instr, dst, src, imm): - return pinsr(ir, instr, dst, src, imm, 64) - - -def pextr(_, instr, dst, src, imm, size): - e = [] - - mask = {8: 0xF, - 16: 0x7, - 32: 0x3, - 64: 0x1}[size] - - sel = (int(imm) & mask) * size - e.append(m2_expr.ExprAssign(dst, src[sel:sel + size].zeroExtend(dst.size))) - - return e, [] - - -def pextrb(ir, instr, dst, src, imm): - return pextr(ir, instr, dst, src, imm, 8) - - -def pextrw(ir, instr, dst, src, imm): - return pextr(ir, instr, dst, src, imm, 16) - - -def pextrd(ir, instr, dst, src, imm): - return pextr(ir, instr, dst, src, imm, 32) - - -def pextrq(ir, instr, dst, src, imm): - return pextr(ir, instr, dst, src, imm, 64) - - -def unpckhps(_, instr, dst, src): - e = [] - src = m2_expr.ExprCompose(dst[64:96], src[64:96], dst[96:128], src[96:128]) - e.append(m2_expr.ExprAssign(dst, src)) - return e, [] - - -def unpckhpd(_, instr, dst, src): - e = [] - src = m2_expr.ExprCompose(dst[64:128], src[64:128]) - e.append(m2_expr.ExprAssign(dst, src)) - return e, [] - - -def unpcklps(_, instr, dst, src): - e = [] - src = m2_expr.ExprCompose(dst[0:32], src[0:32], dst[32:64], src[32:64]) - e.append(m2_expr.ExprAssign(dst, src)) - return e, [] - - -def unpcklpd(_, instr, dst, src): - e = [] - src = m2_expr.ExprCompose(dst[0:64], src[0:64]) - e.append(m2_expr.ExprAssign(dst, src)) - return e, [] - - -def movlpd(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[:64], src[:64])) - return e, [] - - -def movlps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[:64], src[:64])) - return e, [] - - -def movhpd(_, instr, dst, src): - e = [] - if src.size == 64: - e.append(m2_expr.ExprAssign(dst[64:128], src)) - elif dst.size == 64: - e.append(m2_expr.ExprAssign(dst, src[64:128])) - else: - raise RuntimeError("bad encoding!") - return e, [] - - -def movlhps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[64:128], src[:64])) - return e, [] - - -def movhlps(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[:64], src[64:128])) - return e, [] - - -def movdq2q(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, src[:64])) - return e, [] - - -def movq2dq(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst, src[:64].zeroExtend(dst.size))) - return e, [] - - -def sqrt_gen(_, instr, dst, src, size): - e = [] - out = [] - for i in range(src.size // size): - out.append(m2_expr.ExprOp('fsqrt', - src[i * size: (i + 1) * size])) - src = m2_expr.ExprCompose(*out) - e.append(m2_expr.ExprAssign(dst, src)) - return e, [] - - -def sqrtpd(ir, instr, dst, src): - return sqrt_gen(ir, instr, dst, src, 64) - - -def sqrtps(ir, instr, dst, src): - return sqrt_gen(ir, instr, dst, src, 32) - - -def sqrtsd(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[:64], - m2_expr.ExprOp('fsqrt', - src[:64]))) - return e, [] - - -def sqrtss(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAssign(dst[:32], - m2_expr.ExprOp('fsqrt', - src[:32]))) - return e, [] - - -def pmovmskb(_, instr, dst, src): - e = [] - out = [] - for i in range(src.size // 8): - out.append(src[8 * i + 7:8 * (i + 1)]) - src = m2_expr.ExprCompose(*out) - e.append(m2_expr.ExprAssign(dst, src.zeroExtend(dst.size))) - return e, [] - - -def smsw(ir, instr, dst): - e = [] - LOG_X86_SEM.warning("DEFAULT SMSW %s!!", str(dst)) - e.append(m2_expr.ExprAssign(dst, m2_expr.ExprInt(0x80050033, 32)[:dst.size])) - return e, [] - - -def bndmov(ir, instr, dst, src): - # Implemented as a NOP, because BND side effects are not yet supported - return [], [] - -def palignr(ir, instr, dst, src, imm): - # dst.src >> imm * 8 [:dst.size] - - shift = int(imm) * 8 - if shift == 0: - result = src - elif shift == src.size: - result = dst - elif shift > src.size: - result = dst >> m2_expr.ExprInt(shift - src.size, dst.size) - else: - # shift < src.size - result = m2_expr.ExprCompose( - src[shift:], - dst[:shift], - ) - - return [m2_expr.ExprAssign(dst, result)], [] - - -def _signed_to_signed_saturation(expr, dst_size): - """Saturate the expr @expr for @dst_size bit - Signed saturation return MAX_INT / MIN_INT or value depending on the value - """ - assert expr.size > dst_size - - median = 1 << (dst_size - 1) - - min_int = m2_expr.ExprInt(- median, dst_size) - max_int = m2_expr.ExprInt(median - 1, dst_size) - - test_min_int = min_int.signExtend(expr.size) - test_max_int = max_int.signExtend(expr.size) - - value = expr[:dst_size] - - return m2_expr.ExprCond( - m2_expr.ExprOp( - m2_expr.TOK_INF_EQUAL_SIGNED, - expr, - test_min_int - ), - min_int, - m2_expr.ExprCond( - m2_expr.ExprOp( - m2_expr.TOK_INF_SIGNED, - expr, - test_max_int - ), - value, - max_int - ) - ) - - -def _signed_to_unsigned_saturation(expr, dst_size): - """Saturate the expr @expr for @dst_size bit - Unsigned saturation return MAX_INT or value depending on the value - """ - assert expr.size > dst_size - - zero = m2_expr.ExprInt(0, dst_size) - test_zero = m2_expr.ExprInt(0, expr.size) - - max_int = m2_expr.ExprInt(-1, dst_size) - test_max_int = max_int.zeroExtend(expr.size) - - value = expr[:dst_size] - - return m2_expr.ExprCond( - m2_expr.ExprOp( - m2_expr.TOK_INF_EQUAL_SIGNED, - expr, - test_zero - ), - zero, - m2_expr.ExprCond( - m2_expr.ExprOp( - m2_expr.TOK_INF_SIGNED, - expr, - test_max_int - ), - value, - max_int - ) - ) - - - -def packsswb(ir, instr, dst, src): - out = [] - for source in [dst, src]: - for start in range(0, dst.size, 16): - out.append(_signed_to_signed_saturation(source[start:start + 16], 8)) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def packssdw(ir, instr, dst, src): - out = [] - for source in [dst, src]: - for start in range(0, dst.size, 32): - out.append(_signed_to_signed_saturation(source[start:start + 32], 16)) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def packuswb(ir, instr, dst, src): - out = [] - for source in [dst, src]: - for start in range(0, dst.size, 16): - out.append(_signed_to_unsigned_saturation(source[start:start + 16], 8)) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def _saturation_sub_unsigned(expr): - assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") - - # Compute the soustraction on one more bit to be able to distinguish cases: - # 0x48 - 0xd7 in 8 bit, should saturate - arg1 = expr.args[0].zeroExtend(expr.size + 1) - arg2 = expr.args[1].args[0].zeroExtend(expr.size + 1) - return _signed_to_unsigned_saturation(arg1 - arg2, expr.size) - -def _saturation_sub_signed(expr): - assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") - - # Compute the subtraction on two more bits, see _saturation_sub_unsigned - arg1 = expr.args[0].signExtend(expr.size + 2) - arg2 = expr.args[1].args[0].signExtend(expr.size + 2) - return _signed_to_signed_saturation(arg1 - arg2, expr.size) - -def _saturation_add(expr): - assert expr.is_op("+") and len(expr.args) == 2 - - # Compute the addition on one more bit to be able to distinguish cases: - # 0x48 + 0xd7 in 8 bit, should saturate - - arg1 = expr.args[0].zeroExtend(expr.size + 1) - arg2 = expr.args[1].zeroExtend(expr.size + 1) - - # We can also use _signed_to_unsigned_saturation with two additional bits (to - # distinguish minus and overflow case) - # The resulting expression being more complicated with an impossible case - # (signed=True), we rewrite the rule here - - return m2_expr.ExprCond((arg1 + arg2).msb(), m2_expr.ExprInt(-1, expr.size), - expr) - -def _saturation_add_signed(expr): - assert expr.is_op("+") and len(expr.args) == 2 - - # Compute the subtraction on two more bits, see _saturation_add_unsigned - - arg1 = expr.args[0].signExtend(expr.size + 2) - arg2 = expr.args[1].signExtend(expr.size + 2) - - return _signed_to_signed_saturation(arg1 + arg2, expr.size) - - -# Saturate SSE operations - -psubusb = vec_vertical_instr('-', 8, _saturation_sub_unsigned) -psubusw = vec_vertical_instr('-', 16, _saturation_sub_unsigned) -paddusb = vec_vertical_instr('+', 8, _saturation_add) -paddusw = vec_vertical_instr('+', 16, _saturation_add) -psubsb = vec_vertical_instr('-', 8, _saturation_sub_signed) -psubsw = vec_vertical_instr('-', 16, _saturation_sub_signed) -paddsb = vec_vertical_instr('+', 8, _saturation_add_signed) -paddsw = vec_vertical_instr('+', 16, _saturation_add_signed) - - -# Others SSE operations - -def maskmovq(ir, instr, src, mask): - loc_next = ir.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) - blks = [] - - # For each possibility, check if a write is necessary - check_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) - for _ in range(0, mask.size, 8)] - # If the write has to be done, do it (otherwise, nothing happen) - write_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) - for _ in range(0, mask.size, 8)] - - # Build check blocks - for i, start in enumerate(range(0, mask.size, 8)): - bit = mask[start + 7: start + 8] - cur_label = check_labels[i] - next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr - write_label = write_labels[i] - check = m2_expr.ExprAssign(ir.IRDst, - m2_expr.ExprCond(bit, - write_label, - next_check_label)) - blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([check], instr)])) - - # Build write blocks - dst_addr = mRDI[instr.mode] - for i, start in enumerate(range(0, mask.size, 8)): - cur_label = write_labels[i] - next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr - write_addr = dst_addr + m2_expr.ExprInt(i, dst_addr.size) - - # @8[DI/EDI/RDI + i] = src[byte i] - write_mem = m2_expr.ExprAssign(m2_expr.ExprMem(write_addr, 8), - src[start: start + 8]) - jump = m2_expr.ExprAssign(ir.IRDst, next_check_label) - blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([write_mem, jump], instr)])) - - # If mask is null, bypass all - e = [m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(mask, - check_labels[0], - loc_next_expr))] - return e, blks - - -def emms(ir, instr): - # Implemented as a NOP - return [], [] - -def incssp(ir, instr, dst): - # Implemented as a NOP - return [], [] - -def rdssp(ir, instr, dst): - # Implemented as a NOP - return [], [] - -def saveprevssp(ir, instr): - # Implemented as a NOP - return [], [] - -def rstorssp(ir, instr, dst): - # Implemented as a NOP - return [], [] - -def wrss(ir, instr, src, dst): - # Implemented as a NOP - return [], [] - -def wruss(ir, instr, src, dst): - # Implemented as a NOP - return [], [] - -def setssbsy(ir, instr): - # Implemented as a NOP - return [], [] - -def clrssbsy(ir, instr, dst): - # Implemented as a NOP - return [], [] - -def endbr64(ir, instr): - # Implemented as a NOP - return [], [] - -def endbr32(ir, instr): - # Implemented as a NOP - return [], [] - -# Common value without too many option, 0x1fa0 -STMXCSR_VALUE = 0x1fa0 -def stmxcsr(ir, instr, dst): - return [m2_expr.ExprAssign(dst, m2_expr.ExprInt(STMXCSR_VALUE, dst.size))], [] - -def ldmxcsr(ir, instr, dst): - # Implemented as a NOP - return [], [] - - -def _select4(src, control): - # Implementation inspired from Intel Intrinsics Guide - # @control is already resolved (was an immediate) - - if control == 0: - return src[:32] # 0 - elif control == 1: - return src[32:64] - elif control == 2: - return src[64:96] - elif control == 3: - return src[96:] - else: - raise ValueError("Control must be on 2 bits") - - -def shufps(ir, instr, dst, src, imm8): - out = [] - control = int(imm8) - for i in range(4): - if i < 2: - source = dst - else: - source = src - out.append(_select4(source, (control >> (i * 2)) & 3)) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - - -def shufpd(ir, instr, dst, src, imm8): - out = [] - control = int(imm8) - out.append(dst[64:] if control & 1 else dst[:64]) - out.append(src[64:] if control & 2 else src[:64]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out))], [] - -def movmskps(ir, instr, dst, src): - out = [] - for i in range(4): - out.append(src[(32 * i) + 31:(32 * i) + 32]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], [] - -def movmskpd(ir, instr, dst, src): - out = [] - for i in range(2): - out.append(src[(64 * i) + 63:(64 * i) + 64]) - return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], [] - -def _roundscalar(ir, inst, dst, src, imm8, double): - res = None - ctl = int(imm8) - dst_expr = dst[:64] if double else dst[:32] - src_expr = src[:64] if double else src[:32] - if ctl & 0x4 != 0: - # Use MXCSR rounding config - # TODO: here we assume it's round to nearest, ties to even - res = m2_expr.ExprOp('fpround_towardsnearest', src_expr) - else: - # Use encoded rounding mechanism - rounding_mechanism = ctl & 0x3 - ROUNDING_MODE = { - 0x0: 'fpround_towardsnearest', - 0x1: 'fpround_down', - 0x2: 'fpround_up', - 0x3: 'fpround_towardszero' - } - res = m2_expr.ExprOp(ROUNDING_MODE[rounding_mechanism], src_expr) - return [m2_expr.ExprAssign(dst_expr, res)], [] - -def roundss(ir, inst, dst, src, imm8): - return _roundscalar(ir, inst, dst, src, imm8, False) - -def roundsd(ir, inst, dst, src, imm8): - return _roundscalar(ir, inst, dst, src, imm8, True) - -def fxsave(_ir, _instr, _src): - # Implemented as a NOP for now - return [], [] - -def fxrstor(_ir, _instr, _dst): - # Implemented as a NOP for now - return [], [] - - -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, - 'pxor': pxor, - 'or': l_or, - 'and': l_and, - 'test': l_test, - 'rol': l_rol, - 'ror': l_ror, - 'rcl': rcl, - 'rcr': rcr, - 'sar': sar, - 'shr': shr, - 'sal': shl, - 'shl': shl, - '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, - 'pushw': pushw, - 'pop': pop, - 'popw': popw, - '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), - 'cmpsq': lambda ir, instr: cmps(ir, instr, 64), - 'scasb': lambda ir, instr: scas(ir, instr, 8), - 'scasw': lambda ir, instr: scas(ir, instr, 16), - 'scasd': lambda ir, instr: scas(ir, instr, 32), - 'scasq': lambda ir, instr: scas(ir, instr, 64), - 'pushfd': pushfd, - 'pushfq': pushfq, - 'pushfw': pushfw, - 'popfd': popfd, - 'popfq': popfd, - 'popfw': popfw, - 'pusha': pusha, - 'pushad': pushad, - 'popad': popad, - 'popa': popa, - 'call': call, - 'ret': ret, - 'retf': retf, - 'iret': iret, - 'iretd': iret, - 'leave': leave, - 'enter': enter, - 'jmp': jmp, - '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, - '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, - 'das': das, - '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), - 'lodsq': lambda ir, instr: lods(ir, instr, 64), - - 'movsb': lambda ir, instr: movs(ir, instr, 8), - 'movsw': lambda ir, instr: movs(ir, instr, 16), - 'movsd': movsd_dispatch, - 'movsq': lambda ir, instr: movs(ir, instr, 64), - 'fcomp': fcomp, - 'fcompp': fcompp, - 'ficomp': ficomp, - 'fucom': fucom, - 'fucomp': fucomp, - 'fucompp': fucompp, - 'comiss': comiss, - 'comisd': comisd, - 'nop': nop, - 'ud2': ud2, - 'prefetch0': prefetch0, - 'prefetch1': prefetch1, - 'prefetch2': prefetch2, - 'prefetchw': prefetchw, - 'prefetchnta': prefetchnta, - 'lfence': lfence, - 'mfence': mfence, - 'sfence': sfence, - 'fnop': nop, # XXX - 'hlt': hlt, - 'rdtsc': rdtsc, - 'fst': fst, - 'fstp': fstp, - 'fist': fist, - 'fistp': fistp, - 'fisttp': fisttp, - 'fld': fld, - 'fldz': fldz, - 'fld1': fld1, - 'fldl2t': fldl2t, - 'fldpi': fldpi, - 'fldln2': fldln2, - 'fldl2e': fldl2e, - 'fldlg2': fldlg2, - 'fild': fild, - 'fadd': fadd, - 'fiadd': fiadd, - 'fisub': fisub, - 'fisubr': fisubr, - 'fpatan': fpatan, - 'fprem': fprem, - 'fprem1': fprem1, - 'fninit': fninit, - 'fyl2x': fyl2x, - 'faddp': faddp, - 'fsub': fsub, - 'fsubp': fsubp, - 'fsubr': fsubr, - 'fsubrp': fsubrp, - 'fmul': fmul, - 'fimul': fimul, - 'fmulp': fmulp, - 'fdiv': fdiv, - 'fdivr': fdivr, - 'fdivrp': fdivrp, - 'fidiv': fidiv, - 'fidivr': fidivr, - 'fdivp': fdivp, - 'fxch': fxch, - 'fptan': fptan, - 'frndint': frndint, - 'fsin': fsin, - 'fcos': fcos, - 'fsincos': fsincos, - 'fscale': fscale, - 'f2xm1': f2xm1, - 'fchs': fchs, - 'fsqrt': fsqrt, - 'fabs': fabs, - 'fnstsw': fnstsw, - 'fnstcw': fnstcw, - 'fldcw': fldcw, - 'fwait': fwait, - 'fcmovb': fcmovb, - 'fcmove': fcmove, - 'fcmovbe': fcmovbe, - 'fcmovu': fcmovu, - 'fcmovnb': fcmovnb, - 'fcmovne': fcmovne, - 'fcmovnbe': fcmovnbe, - 'fcmovnu': fcmovnu, - 'fnstenv': fnstenv, - 'fldenv': fldenv, - 'sidt': sidt, - 'sldt': sldt, - 'arpl': arpl, - 'cmovz': cmovz, - 'cmove': cmovz, - 'cmovnz': cmovnz, - 'cmovpe': cmovpe, - 'cmovnp': cmovnp, - '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, - 'fcom': fcom, - 'ftst': ftst, - 'fxam': fxam, - '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, - "syscall": l_syscall, - "cmpxchg": cmpxchg, - "cmpxchg8b": cmpxchg8b, - "lds": lds, - "les": les, - "lss": lss, - "lfs": lfs, - "lgs": lgs, - "lahf": lahf, - "sahf": sahf, - "lar": lar, - "lsl": lsl, - "fclex": fclex, - "fnclex": fnclex, - "str": l_str, - "movd": movd, - "movdqu": movdqu, - "movdqa": movdqu, - "movapd": movapd, # XXX TODO alignment check - "movupd": movapd, # XXX TODO alignment check - "movaps": movapd, # XXX TODO alignment check - "movups": movapd, # XXX TODO alignment check - "andps": andps, - "andpd": andps, - "andnps": andnps, - "andnpd": andnps, - "orps": orps, - "orpd": orps, - "xorps": xorps, - "xorpd": xorps, - - "movq": movq, - - "pminsw": pminsw, - "cvtdq2pd": cvtdq2pd, - "cvtdq2ps": cvtdq2ps, - "cvtpd2dq": cvtpd2dq, - "cvtpd2pi": cvtpd2pi, - "cvtpd2ps": cvtpd2ps, - "cvtpi2pd": cvtpi2pd, - "cvtpi2ps": cvtpi2ps, - "cvtps2dq": cvtps2dq, - "cvtps2pd": cvtps2pd, - "cvtps2pi": cvtps2pi, - "cvtsd2si": cvtsd2si, - "cvtsd2ss": cvtsd2ss, - "cvtsi2sd": cvtsi2sd, - "cvtsi2ss": cvtsi2ss, - "cvtss2sd": cvtss2sd, - "cvtss2si": cvtss2si, - "cvttpd2pi": cvttpd2pi, - "cvttpd2dq": cvttpd2dq, - "cvttps2dq": cvttps2dq, - "cvttps2pi": cvttps2pi, - "cvttsd2si": cvttsd2si, - "cvttss2si": cvttss2si, - - - "bndmov": bndmov, - - - - - "movss": movss, - - "ucomiss": ucomiss, - "ucomisd": ucomisd, - - # BMI operations - "blsi": blsi, - "andn": andn, - "bextr": bextr, - "blsmsk": blsmsk, - "blsr": blsr, - "tzcnt": tzcnt, - "bzhi": bzhi, - - # - # MMX/AVX/SSE operations - - # Arithmetic (integers) - # - - # Additions - # SSE - "paddb": paddb, - "paddw": paddw, - "paddd": paddd, - "paddq": paddq, - - # Substractions - # SSE - "psubb": psubb, - "psubw": psubw, - "psubd": psubd, - "psubq": psubq, - - # Multiplications - # SSE - "pmullb": pmullb, - "pmullw": pmullw, - "pmulld": pmulld, - "pmullq": pmullq, - "pmulhub": pmulhub, - "pmulhuw": pmulhuw, - "pmulhud": pmulhud, - "pmulhuq": pmulhuq, - "pmulhb": pmulhb, - "pmulhw": pmulhw, - "pmulhd": pmulhd, - "pmulhq": pmulhq, - "pmuludq": pmuludq, - - # Mix - # SSE - "pmaddwd": pmaddwd, - "psadbw": psadbw, - "pavgb": pavgb, - "pavgw": pavgw, - - # Arithmetic (floating-point) - # - - # Additions - # SSE - "addss": addss, - "addsd": addsd, - "addps": addps, - "addpd": addpd, - - # Substractions - # SSE - "subss": subss, - "subsd": subsd, - "subps": subps, - "subpd": subpd, - - # Multiplications - # SSE - "mulss": mulss, - "mulsd": mulsd, - "mulps": mulps, - "mulpd": mulpd, - - # Divisions - # SSE - "divss": divss, - "divsd": divsd, - "divps": divps, - "divpd": divpd, - - # Rounding - "roundss": roundss, - "roundsd": roundsd, - - # Comparisons (floating-point) - # - "minps": minps, - "minpd": minpd, - "minss": minss, - "minsd": minsd, - "maxps": maxps, - "maxpd": maxpd, - "maxss": maxss, - "maxsd": maxsd, - "cmpeqps": cmpeqps, - "cmpeqpd": cmpeqpd, - "cmpeqss": cmpeqss, - "cmpeqsd": cmpeqsd, - "cmpltps": cmpltps, - "cmpltpd": cmpltpd, - "cmpltss": cmpltss, - "cmpltsd": cmpltsd, - "cmpleps": cmpleps, - "cmplepd": cmplepd, - "cmpless": cmpless, - "cmplesd": cmplesd, - "cmpunordps": cmpunordps, - "cmpunordpd": cmpunordpd, - "cmpunordss": cmpunordss, - "cmpunordsd": cmpunordsd, - "cmpneqps": cmpneqps, - "cmpneqpd": cmpneqpd, - "cmpneqss": cmpneqss, - "cmpneqsd": cmpneqsd, - "cmpnltps": cmpnltps, - "cmpnltpd": cmpnltpd, - "cmpnltss": cmpnltss, - "cmpnltsd": cmpnltsd, - "cmpnleps": cmpnleps, - "cmpnlepd": cmpnlepd, - "cmpnless": cmpnless, - "cmpnlesd": cmpnlesd, - "cmpordps": cmpordps, - "cmpordpd": cmpordpd, - "cmpordss": cmpordss, - "cmpordsd": cmpordsd, - - # Logical (floating-point) - # - - "pand": pand, - "pandn": pandn, - "por": por, - - "rdmsr": rdmsr, - "wrmsr": wrmsr, - "pshufb": pshufb, - "pshufd": pshufd, - "pshuflw": pshuflw, - "pshufhw": pshufhw, - - "psrlw": psrlw, - "psrld": psrld, - "psrlq": psrlq, - "psllw": psllw, - "pslld": pslld, - "psllq": psllq, - "pslldq": pslldq, - "psrldq": psrldq, - "psraw": psraw, - "psrad": psrad, - - "palignr": palignr, - - "pmaxub": pmaxub, - "pmaxuw": pmaxuw, - "pmaxud": pmaxud, - "pmaxsw": pmaxsw, - - "pminub": pminub, - "pminuw": pminuw, - "pminud": pminud, - - "pcmpeqb": pcmpeqb, - "pcmpeqw": pcmpeqw, - "pcmpeqd": pcmpeqd, - "pcmpeqq": pcmpeqq, - - "pcmpgtb": pcmpgtb, - "pcmpgtw": pcmpgtw, - "pcmpgtd": pcmpgtd, - "pcmpgtq": pcmpgtq, - - "punpckhbw": punpckhbw, - "punpckhwd": punpckhwd, - "punpckhdq": punpckhdq, - "punpckhqdq": punpckhqdq, - - - "punpcklbw": punpcklbw, - "punpcklwd": punpcklwd, - "punpckldq": punpckldq, - "punpcklqdq": punpcklqdq, - - "pinsrb": pinsrb, - "pinsrw": pinsrw, - "pinsrd": pinsrd, - "pinsrq": pinsrq, - - "pextrb": pextrb, - "pextrw": pextrw, - "pextrd": pextrd, - "pextrq": pextrq, - - "unpckhps": unpckhps, - "unpckhpd": unpckhpd, - "unpcklps": unpcklps, - "unpcklpd": unpcklpd, - - "movlpd": movlpd, - "movlps": movlps, - "movhpd": movhpd, - "movhps": movhpd, - "movlhps": movlhps, - "movhlps": movhlps, - "movdq2q": movdq2q, - "movq2dq": movq2dq, - - "sqrtpd": sqrtpd, - "sqrtps": sqrtps, - "sqrtsd": sqrtsd, - "sqrtss": sqrtss, - - "pmovmskb": pmovmskb, - - "packsswb": packsswb, - "packssdw": packssdw, - "packuswb": packuswb, - - "psubusb": psubusb, - "psubusw": psubusw, - "paddusb": paddusb, - "paddusw": paddusw, - "psubsb": psubsb, - "psubsw": psubsw, - "paddsb": paddsb, - "paddsw": paddsw, - - "smsw": smsw, - "maskmovq": maskmovq, - "maskmovdqu": maskmovq, - "emms": emms, - "shufps": shufps, - "shufpd": shufpd, - "movmskps": movmskps, - "movmskpd": movmskpd, - "stmxcsr": stmxcsr, - "ldmxcsr": ldmxcsr, - - # CET (Control-flow Enforcement Technology) - "incssp": incssp, - "rdssp": rdssp, - "saveprevssp": saveprevssp, - "rstorssp": rstorssp, - "wrss": wrss, - "wruss": wruss, - "setssbsy": setssbsy, - "clrssbsy": clrssbsy, - "endbr64": endbr64, - "endbr32": endbr32, - "fxsave": fxsave, - "fxrstor": fxrstor, - } - - -class Lifter_X86_16(Lifter): - - def __init__(self, loc_db): - Lifter.__init__(self, mn_x86, 16, loc_db) - 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 - self.IRDst = m2_expr.ExprId('IRDst', 16) - # Size of memory pointer access in IR - # 16 bit mode memory accesses may be greater than 16 bits - # 32 bit size may be enough - self.addrsize = 32 - - def mod_pc(self, instr, instr_ir, extra_ir): - pass - - def ExprMem(self, ptr, size): - """Generate a memory access to @ptr - The ptr is resized to a fixed size self.addrsize - - @ptr: Expr instance to the memory address - @size: size of the memory""" - - return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size) - - def gen_segm_expr(self, selector, addr): - ptr = m2_expr.ExprOp( - 'segm', - selector, - addr.zeroExtend(self.addrsize) - ) - - return ptr - - def get_ir(self, instr): - args = instr.args[:] - args = [arg.replace_expr(float_replace) for arg in args] - args = fix_mem_args_size(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 a.is_mem() and not is_mem_segm(a): - args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, - a.ptr), a.size) - - if not instr.name.lower() in mnemo_func: - raise NotImplementedError( - "Mnemonic %s not implemented" % instr.name) - - instr_ir, extra_ir = mnemo_func[ - instr.name.lower()](self, instr, *args) - self.mod_pc(instr, instr_ir, extra_ir) - instr.additional_info.except_on_instr = False - if instr.additional_info.g1.value & 14 == 0 or \ - not instr.name in repeat_mn: - return instr_ir, extra_ir - if instr.name == "MOVSD" and len(instr.args) == 2: - return instr_ir, extra_ir - - instr.additional_info.except_on_instr = True - admode = instr.v_admode() - c_reg = mRCX[instr.mode][:admode] - - 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 - - cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), - m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) - # end condition - if zf_val is None: - c_cond = cond_dec - elif instr.additional_info.g1.value & 2: # REPNE and REPNZ - c_cond = cond_dec | zf - elif instr.additional_info.g1.value & 12: # REPE, REP and REPZ - c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) - - # gen while - loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) - loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) - loc_skip = self.get_next_loc_key(instr) - loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) - loc_next = self.get_next_loc_key(instr) - loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) - - fix_next_loc = {loc_next_expr: loc_end_expr} - new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) - for irblock in extra_ir] - - cond_bloc = [] - cond_bloc.append(m2_expr.ExprAssign(c_reg, - c_reg - m2_expr.ExprInt(1, - c_reg.size))) - cond_bloc.append(m2_expr.ExprAssign(self.IRDst, m2_expr.ExprCond(c_cond, - loc_skip_expr, - loc_do_expr))) - cond_bloc = IRBlock(self.loc_db, loc_end, [AssignBlock(cond_bloc, instr)]) - e_do = instr_ir - - c = IRBlock(self.loc_db, loc_do, [AssignBlock(e_do, instr)]) - e_n = [m2_expr.ExprAssign(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, - loc_skip_expr))] - return e_n, [cond_bloc, c] + new_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 m2_expr.ExprAssign(dst, src) - - def irbloc_fix_regs_for_mode(self, irblock, mode=64): - irs = [] - for assignblk in irblock: - new_assignblk = dict(assignblk) - for dst, src in viewitems(assignblk): - del new_assignblk[dst] - # Special case for 64 bits: - # If destination is a 32 bit reg, zero extend the 64 bit reg - if mode == 64: - if (isinstance(dst, m2_expr.ExprId) and - dst.size == 32 and - dst in replace_regs[64]): - src = src.zeroExtend(64) - dst = replace_regs[64][dst].arg - dst = self.expr_fix_regs_for_mode(dst, mode) - src = self.expr_fix_regs_for_mode(src, mode) - new_assignblk[dst] = src - irs.append(AssignBlock(new_assignblk, assignblk.instr)) - return IRBlock(self.loc_db, irblock.loc_key, irs) - - -class Lifter_X86_32(Lifter_X86_16): - - def __init__(self, loc_db): - Lifter.__init__(self, mn_x86, 32, loc_db) - 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 - self.IRDst = m2_expr.ExprId('IRDst', 32) - self.addrsize = 32 - - -class Lifter_X86_64(Lifter_X86_16): - - def __init__(self, loc_db): - Lifter.__init__(self, mn_x86, 64, loc_db) - 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 - self.IRDst = m2_expr.ExprId('IRDst', 64) - self.addrsize = 64 - - def mod_pc(self, instr, instr_ir, extra_ir): - # fix RIP for 64 bit - pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)} - - for i, expr in enumerate(instr_ir): - dst, src = expr.dst, expr.src - if dst != self.pc: - dst = dst.replace_expr(pc_fixed) - src = src.replace_expr(pc_fixed) - instr_ir[i] = m2_expr.ExprAssign(dst, src) - - for idx, irblock in enumerate(extra_ir): - extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \ - if expr != self.pc else expr, - lambda expr: expr.replace_expr(pc_fixed)) |