diff options
| -rw-r--r-- | miasm2/arch/mep/sem.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/mips32/ira.py | 106 | ||||
| -rw-r--r-- | miasm2/arch/mips32/regs.py | 1 | ||||
| -rw-r--r-- | miasm2/arch/mips32/sem.py | 53 | ||||
| -rw-r--r-- | miasm2/arch/x86/sem.py | 111 | ||||
| -rw-r--r-- | miasm2/core/cpu.py | 3 | ||||
| -rw-r--r-- | miasm2/expression/expression.py | 16 | ||||
| -rw-r--r-- | miasm2/expression/expression_helper.py | 2 | ||||
| -rw-r--r-- | miasm2/expression/simplifications.py | 3 | ||||
| -rw-r--r-- | miasm2/expression/simplifications_common.py | 111 | ||||
| -rw-r--r-- | miasm2/expression/simplifications_explicit.py | 11 | ||||
| -rw-r--r-- | miasm2/ir/translators/C.py | 25 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 4 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.c | 10 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.h | 5 | ||||
| -rw-r--r-- | test/arch/mep/ir/test_divide.py | 24 | ||||
| -rw-r--r-- | test/expression/simplifications.py | 9 | ||||
| -rwxr-xr-x | test/ir/ir2C.py | 4 |
18 files changed, 316 insertions, 189 deletions
diff --git a/miasm2/arch/mep/sem.py b/miasm2/arch/mep/sem.py index e1d4c5fa..e779b970 100644 --- a/miasm2/arch/mep/sem.py +++ b/miasm2/arch/mep/sem.py @@ -912,7 +912,12 @@ def div(rn, rm): # Check if both numbers are positive or negative are_both_neg = sign_rn & sign_rm - are_both_pos = "=="(are_both_neg, sign_mask) + are_both_pos = ExprCond( + are_both_neg - sign_mask, + ExprInt(0, are_both_neg.size), + ExprInt(1, are_both_neg.size) + ) + # Invert both numbers rn_inv = ~rn + i32(1) diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py index def75750..4c4a33d8 100644 --- a/miasm2/arch/mips32/ira.py +++ b/miasm2/arch/mips32/ira.py @@ -1,7 +1,7 @@ #-*- coding:utf-8 -*- -from miasm2.expression.expression import ExprAff, ExprInt, ExprId -from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock +from miasm2.expression.expression import ExprAff, ExprOp +from miasm2.ir.ir import IRBlock, AssignBlock from miasm2.ir.analysis import ira from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b @@ -10,41 +10,73 @@ class ir_a_mips32l(ir_mips32l, ira): ir_mips32l.__init__(self, loc_db) self.ret_reg = self.arch.regs.V0 - def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): - IntermediateRepresentation.post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks) - new_irblocks = [] - for irb in ir_blocks: - pc_val = None - lr_val = None - for assignblk in irb: - pc_val = assignblk.get(self.arch.regs.PC, pc_val) - lr_val = assignblk.get(self.arch.regs.RA, lr_val) - - if pc_val is None or lr_val is None: - new_irblocks.append(irb) - continue - if lr_val.is_loc(): - offset = self.loc_db.get_location_offset(lr_val.loc_key) - if offset is not None: - lr_val = ExprInt(offset, 32) - if not lr_val.is_int(): - continue - - instr = block.lines[-2] - if int(lr_val) != instr.offset + 8: - raise ValueError("Wrong arg") - - # CALL - lbl = block.get_next() - new_lbl = self.gen_label() - call_assignblks, extra_irblocks = self.call_effects(pc_val, instr) - ir_blocks += extra_irblocks - irs.append(AssignBlock([ExprAff(self.IRDst, - ExprId(lbl, size=self.pc.size))], - instr)) - new_irblocks.append(IRBlock(new_lbl, call_assignblks)) - new_irblocks.append(irb.set_dst(ExprId(new_lbl, size=self.pc.size))) - return new_irblocks + def call_effects(self, ad, instr): + call_assignblk = AssignBlock( + [ + ExprAff( + self.ret_reg, + ExprOp( + 'call_func_ret', + ad, + self.arch.regs.A0, + self.arch.regs.A1, + self.arch.regs.A2, + self.arch.regs.A3, + ) + ), + ], + instr + ) + + return [call_assignblk], [] + + + def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): + """ + Add a native block to the current IR + @block: native assembly block + @ircfg: IRCFG instance + @gen_pc_updt: insert PC update effects between instructions + """ + loc_key = block.loc_key + ir_blocks_all = [] + + assignments = [] + for index, instr in enumerate(block.lines): + if loc_key is None: + assignments = [] + loc_key = self.get_loc_key_for_instr(instr) + if instr.is_subcall(): + assert index == len(block.lines) - 2 + + # Add last instruction first (before call) + split = self.add_instr_to_current_state( + block.lines[-1], block, assignments, + ir_blocks_all, gen_pc_updt + ) + assert not split + # Add call effects after the delay splot + split = self.add_instr_to_current_state( + instr, block, assignments, + ir_blocks_all, gen_pc_updt + ) + assert split + break + split = self.add_instr_to_current_state( + instr, block, assignments, + ir_blocks_all, gen_pc_updt + ) + if split: + ir_blocks_all.append(IRBlock(loc_key, assignments)) + loc_key = None + assignments = [] + if loc_key is not None: + ir_blocks_all.append(IRBlock(loc_key, assignments)) + + new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) + for irblock in new_ir_blocks_all: + ircfg.add_irblock(irblock) + return new_ir_blocks_all def get_out_regs(self, _): return set([self.ret_reg, self.sp]) diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py index 7ff949f2..ddaaff79 100644 --- a/miasm2/arch/mips32/regs.py +++ b/miasm2/arch/mips32/regs.py @@ -24,6 +24,7 @@ regs32_str = ["ZERO", 'AT', 'V0', 'V1'] +\ ['GP', 'SP', 'FP', 'RA'] regs32_expr = [ExprId(x, 32) for x in regs32_str] +ZERO = regs32_expr[0] regs_flt_str = ['F%d'%i for i in xrange(0x20)] diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py index acf7370f..92001280 100644 --- a/miasm2/arch/mips32/sem.py +++ b/miasm2/arch/mips32/sem.py @@ -1,16 +1,20 @@ import miasm2.expression.expression as m2_expr from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.arch.mips32.arch import mn_mips32 -from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA, exception_flags +from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA, ZERO, exception_flags from miasm2.core.sembuilder import SemBuilder from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO # SemBuilder context -ctx = {"R_LO": R_LO, - "R_HI": R_HI, - "PC": PC, - "RA": RA} +ctx = { + "R_LO": R_LO, + "R_HI": R_HI, + "PC": PC, + "RA": RA, + "m2_expr": m2_expr +} + sbuild = SemBuilder(ctx) @@ -76,7 +80,7 @@ def lb(arg1, arg2): @sbuild.parse def beq(arg1, arg2, arg3): "Branches on @arg3 if the quantities of two registers @arg1, @arg2 are eq" - dst = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if arg1 - arg2 else arg3 + dst = arg3 if ExprOp(m2_expr.TOK_EQUAL, arg1, arg2) else ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) PC = dst ir.IRDst = dst @@ -84,7 +88,7 @@ def beq(arg1, arg2, arg3): def bgez(arg1, arg2): """Branches on @arg2 if the quantities of register @arg1 is greater than or equal to zero""" - dst = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if arg1.msb() else arg2 + dst = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if ExprOp(m2_expr.TOK_INF_SIGNED, arg1, ExprInt(0, arg1.size)) else arg2 PC = dst ir.IRDst = dst @@ -92,7 +96,7 @@ def bgez(arg1, arg2): def bne(arg1, arg2, arg3): """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT equal""" - dst = arg3 if arg1 - arg2 else ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) + dst = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if ExprOp(m2_expr.TOK_EQUAL, arg1, arg2) else arg3 PC = dst ir.IRDst = dst @@ -143,15 +147,24 @@ def mul(arg1, arg2, arg3): @sbuild.parse def sltu(arg1, arg2, arg3): - """If @arg3 is less than @arg2 (unsigned), @arg1 is set to one. It gets zero + """If @arg2 is less than @arg3 (unsigned), @arg1 is set to one. It gets zero otherwise.""" - arg1 = (((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ arg2 ^ arg3).msb().zeroExtend(32) + arg1 = ExprCond( + ExprOp(m2_expr.TOK_INF_UNSIGNED, arg2, arg3), + ExprInt(1, arg1.size), + ExprInt(0, arg1.size) + ) @sbuild.parse def slt(arg1, arg2, arg3): - """If @arg3 is less than @arg2 (signed), @arg1 is set to one. It gets zero + """If @arg2 is less than @arg3 (signed), @arg1 is set to one. It gets zero otherwise.""" - arg1 = ((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb().zeroExtend(32) + arg1 = ExprCond( + ExprOp(m2_expr.TOK_INF_SIGNED, arg2, arg3), + ExprInt(1, arg1.size), + ExprInt(0, arg1.size) + ) + @sbuild.parse def l_sub(arg1, arg2, arg3): @@ -230,14 +243,14 @@ def seh(arg1, arg2): @sbuild.parse def bltz(arg1, arg2): """Branches on @arg2 if the register @arg1 is less than zero""" - dst_o = arg2 if arg1.msb() else ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) + dst_o = arg2 if ExprOp(m2_expr.TOK_INF_SIGNED, arg1, ExprInt(0, arg1.size)) else ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) PC = dst_o ir.IRDst = dst_o @sbuild.parse def blez(arg1, arg2): """Branches on @arg2 if the register @arg1 is less than or equal to zero""" - cond = (i1(1) if arg1 else i1(0)) | arg1.msb() + cond = ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size)) dst_o = arg2 if cond else ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) PC = dst_o ir.IRDst = dst_o @@ -245,7 +258,7 @@ def blez(arg1, arg2): @sbuild.parse def bgtz(arg1, arg2): """Branches on @arg2 if the register @arg1 is greater than zero""" - cond = (i1(1) if arg1 else i1(0)) | arg1.msb() + cond = ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size)) dst_o = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if cond else arg2 PC = dst_o ir.IRDst = dst_o @@ -480,12 +493,15 @@ class ir_mips32l(IntermediateRepresentation): args = instr.args instr_ir, extra_ir = get_mnemo_expr(self, instr, *args) - pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + 4, 32)} + fixed_regs = { + self.pc: m2_expr.ExprInt(instr.offset + 4, 32), + ZERO: m2_expr.ExprInt(0, 32) + } - instr_ir = [m2_expr.ExprAff(expr.dst, expr.src.replace_expr(pc_fixed)) + instr_ir = [m2_expr.ExprAff(expr.dst, expr.src.replace_expr(fixed_regs)) for expr in instr_ir] - new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(pc_fixed)) + new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fixed_regs)) for irblock in extra_ir] return instr_ir, new_extra_ir @@ -497,6 +513,7 @@ class ir_mips32l(IntermediateRepresentation): class ir_mips32b(ir_mips32l): def __init__(self, loc_db=None): + self.addrsize = 32 IntermediateRepresentation.__init__(self, mn_mips32, 'b', loc_db) self.pc = mn_mips32.getpc() self.sp = mn_mips32.getsp() diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index a00b6f7c..ec85ae32 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -321,7 +321,7 @@ def mem2double(instr, arg): if arg.size > 64: # TODO: move to 80 bits arg = m2_expr.ExprMem(expraddr(instr.mode, arg.arg), size=64) - return m2_expr.ExprOp('mem_%.2d_to_double' % arg.size, arg) + return m2_expr.ExprOp('sint_to_fp', arg.signExtend(64)) else: return arg @@ -2091,8 +2091,7 @@ def float_pop(avoid_flt=None, popcount=1): if avoid_flt != float_list[i]: e.append(m2_expr.ExprAff(float_list[i], float_list[i + popcount])) - fill_value = m2_expr.ExprOp("sint_to_fp64", - m2_expr.ExprInt(0, float_list[i].size)) + fill_value = m2_expr.ExprOp("sint_to_fp", m2_expr.ExprInt(0, 64)) for i in xrange(8 - popcount, 8): e.append(m2_expr.ExprAff(float_list[i], fill_value)) @@ -2127,7 +2126,7 @@ def ftst(_, instr): dst = float_st0 e = [] - src = m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(0, 32)) + src = m2_expr.ExprOp('sint_to_fp', m2_expr.ExprInt(0, 64)) e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) @@ -2253,8 +2252,8 @@ def comiss(_, instr, dst, src): e = [] - dst = m2_expr.ExprOp('sint_to_fp32', dst[:32]) - src = m2_expr.ExprOp('sint_to_fp32', src[:32]) + dst = m2_expr.ExprOp('sint_to_fp', dst[:32]) + src = m2_expr.ExprOp('sint_to_fp', src[:32]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) @@ -2273,8 +2272,8 @@ def comisd(_, instr, dst, src): e = [] - dst = m2_expr.ExprOp('sint_to_fp64', dst[:64]) - src = m2_expr.ExprOp('sint_to_fp64', src[:64]) + dst = m2_expr.ExprOp('sint_to_fp', dst[:64]) + src = m2_expr.ExprOp('sint_to_fp', src[:64]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) @@ -2292,6 +2291,8 @@ 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.ExprAff(float_st7, float_st6)) @@ -2377,7 +2378,7 @@ def fisttp(_, instr, dst): def fild(ir, instr, src): # XXXXX - src = m2_expr.ExprOp('sint_to_fp64', src) + src = m2_expr.ExprOp('sint_to_fp', src.signExtend(64)) e = [] e += set_float_cs_eip(instr) e_fld, extra = fld(ir, instr, src) @@ -2386,27 +2387,29 @@ def fild(ir, instr, src): def fldz(ir, instr): - return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', - m2_expr.ExprInt(0, 32))) + 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_fp64', - m2_expr.ExprInt(1, 32))) + 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('I', struct.pack('f', value_f))[0] - return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', - m2_expr.ExprInt(value, 32))) + 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('I', struct.pack('f', value_f))[0] - return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', - m2_expr.ExprInt(value, 32))) + 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): @@ -2745,9 +2748,15 @@ def fptan(_, instr): e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('ftan', float_st0))) - e.append(m2_expr.ExprAff(float_st0, - m2_expr.ExprOp('sint_to_fp64', - m2_expr.ExprInt(1, 32)))) + e.append( + m2_expr.ExprAff( + float_st0, + m2_expr.ExprOp( + 'sint_to_fp', + m2_expr.ExprInt(1, 64) + ) + ) + ) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) @@ -3958,22 +3967,36 @@ def por(_, instr, dst, src): def cvtdq2pd(_, instr, dst, src): e = [] e.append( - m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) + m2_expr.ExprAff( + dst[:64], + m2_expr.ExprOp( + 'sint_to_fp', + src[:32].signExtend(64) + ) + ) + ) e.append( - m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) + m2_expr.ExprAff( + 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.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) + m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) e.append( - m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) + m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp', src[32:64]))) e.append( - m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('sint_to_fp32', src[64:96]))) + m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('sint_to_fp', src[64:96]))) e.append( - m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('sint_to_fp32', src[96:128]))) + m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('sint_to_fp', src[96:128]))) return e, [] @@ -4009,18 +4032,31 @@ def cvtpd2ps(_, instr, dst, src): def cvtpi2pd(_, instr, dst, src): e = [] e.append( - m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) + m2_expr.ExprAff( + dst[:64], + m2_expr.ExprOp( + 'sint_to_fp', + src[:32].signExtend(64) + ) + ) + ) e.append( - m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) + m2_expr.ExprAff( + 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.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) + m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) e.append( - m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) + m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp', src[32:64]))) return e, [] @@ -4072,14 +4108,21 @@ def cvtsd2ss(_, instr, dst, src): def cvtsi2sd(_, instr, dst, src): e = [] e.append( - m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) + m2_expr.ExprAff( + dst[:64], + m2_expr.ExprOp( + 'sint_to_fp', + src[:32].signExtend(64) + ) + ) + ) return e, [] def cvtsi2ss(_, instr, dst, src): e = [] e.append( - m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) + m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp', src[:32]))) return e, [] diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py index 4605a033..071991b7 100644 --- a/miasm2/core/cpu.py +++ b/miasm2/core/cpu.py @@ -11,6 +11,7 @@ import miasm2.expression.expression as m2_expr from miasm2.core.bin_stream import bin_stream, bin_stream_str from miasm2.core.utils import Disasm_Exception from miasm2.expression.simplifications import expr_simp +from miasm2.core.locationdb import LocationDB from miasm2.core.asm_ast import AstNode, AstInt, AstId, AstOp @@ -1012,7 +1013,7 @@ class instruction(object): def resolve_args_with_symbols(self, symbols=None): if symbols is None: - symbols = {} + symbols = LocationDB() args_out = [] for expr in self.args: # try to resolve symbols using symbols (0 for default value) diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py index 954ba00a..69739990 100644 --- a/miasm2/expression/expression.py +++ b/miasm2/expression/expression.py @@ -1009,7 +1009,7 @@ class ExprOp(Expr): # Set size for special cases if self._op in [ - '==', 'parity', 'fcom_c0', 'fcom_c1', 'fcom_c2', 'fcom_c3', + TOK_EQUAL, 'parity', 'fcom_c0', 'fcom_c1', 'fcom_c2', 'fcom_c3', 'fxam_c0', 'fxam_c1', 'fxam_c2', 'fxam_c3', "access_segment_ok", "load_segment_limit_ok", "bcdadd_cf", "ucomiss_zf", "ucomiss_pf", "ucomiss_cf", @@ -1022,8 +1022,6 @@ class ExprOp(Expr): TOK_POS_STRICT, ]: size = 1 - elif self._op.startswith("sint_to_fp"): - size = int(self._op[len("sint_to_fp"):]) elif self._op.startswith("fp_to_sint"): size = int(self._op[len("fp_to_sint"):]) elif self._op.startswith("fpconvert_fp"): @@ -1102,9 +1100,15 @@ class ExprOp(Expr): return self._op.startswith('call') def is_infix(self): - return self._op in [ '-', '+', '*', '^', '&', '|', '>>', '<<', - 'a>>', '>>>', '<<<', '/', '%', '**', - '<u', '<s', '<=u', '<=s', '==' ] + return self._op in [ + '-', '+', '*', '^', '&', '|', '>>', '<<', + 'a>>', '>>>', '<<<', '/', '%', '**', + TOK_INF_UNSIGNED, + TOK_INF_SIGNED, + TOK_INF_EQUAL_UNSIGNED, + TOK_INF_EQUAL_SIGNED, + TOK_EQUAL + ] def is_associative(self): "Return True iff current operation is associative" diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py index bb0d5adf..5de9e04f 100644 --- a/miasm2/expression/expression_helper.py +++ b/miasm2/expression/expression_helper.py @@ -512,7 +512,7 @@ class CondConstraint(object): class CondConstraintZero(CondConstraint): """Stand for a constraint like 'A == 0'""" - operator = "==" + operator = m2_expr.TOK_EQUAL def to_constraint(self): return m2_expr.ExprAff(self.expr, m2_expr.ExprInt(0, self.expr.size)) diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py index d3628ae8..e090d806 100644 --- a/miasm2/expression/simplifications.py +++ b/miasm2/expression/simplifications.py @@ -56,6 +56,9 @@ class ExpressionSimplifier(object): simplifications_common.simp_cond_flag, simplifications_common.simp_cond_int, simplifications_common.simp_cmp_int_arg, + + simplifications_common.simp_cond_eq_zero, + ], m2_expr.ExprMem: [simplifications_common.simp_mem], diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py index b01b1d1d..e7dacc91 100644 --- a/miasm2/expression/simplifications_common.py +++ b/miasm2/expression/simplifications_common.py @@ -4,8 +4,11 @@ from miasm2.expression.modint import mod_size2int, mod_size2uint -from miasm2.expression.expression import ExprInt, ExprSlice, ExprMem, ExprCond, ExprOp, ExprCompose -from miasm2.expression.expression_helper import parity, op_propag_cst, merge_sliceto_slice +from miasm2.expression.expression import ExprInt, ExprSlice, ExprMem, \ + ExprCond, ExprOp, ExprCompose, TOK_INF_SIGNED, TOK_INF_UNSIGNED, \ + TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED, TOK_EQUAL +from miasm2.expression.expression_helper import parity, op_propag_cst, \ + merge_sliceto_slice def simp_cst_propagation(e_s, expr): @@ -692,7 +695,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SUB_CF" )): expr = ExprCond( - ExprOp("<u", *expr.args[0].args), + ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1)) @@ -701,14 +704,14 @@ def simp_cc_conds(expr_simp, expr): expr, "FLAG_SUB_CF" )): - expr = ExprOp("<u", *expr.args[0].args) + expr = ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args) elif (expr.is_op("CC_NEG") and test_cc_eq_args( expr, "FLAG_SIGN_SUB" )): - expr = ExprOp("<s", *expr.args[0].args) + expr = ExprOp(TOK_INF_SIGNED, *expr.args[0].args) elif (expr.is_op("CC_POS") and test_cc_eq_args( @@ -716,7 +719,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SIGN_SUB" )): expr = ExprCond( - ExprOp("<s", *expr.args[0].args), + ExprOp(TOK_INF_SIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -727,7 +730,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_EQ" )): arg = expr.args[0].args[0] - expr = ExprOp("==", arg, ExprInt(0, arg.size)) + expr = ExprOp(TOK_EQUAL, arg, ExprInt(0, arg.size)) elif (expr.is_op("CC_NE") and test_cc_eq_args( @@ -736,7 +739,7 @@ def simp_cc_conds(expr_simp, expr): )): arg = expr.args[0].args[0] expr = ExprCond( - ExprOp("==",arg, ExprInt(0, arg.size)), + ExprOp(TOK_EQUAL,arg, ExprInt(0, arg.size)), ExprInt(0, 1), ExprInt(1, 1) ) @@ -746,7 +749,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_EQ_CMP" )): expr = ExprCond( - ExprOp("==", *expr.args[0].args), + ExprOp(TOK_EQUAL, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -756,7 +759,7 @@ def simp_cc_conds(expr_simp, expr): expr, "FLAG_EQ_CMP" )): - expr = ExprOp("==", *expr.args[0].args) + expr = ExprOp(TOK_EQUAL, *expr.args[0].args) elif (expr.is_op("CC_NE") and test_cc_eq_args( @@ -784,7 +787,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_EQ_CMP", )): expr = ExprCond( - ExprOp("<=s", *expr.args[0].args), + ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -796,7 +799,7 @@ def simp_cc_conds(expr_simp, expr): expr.args[0].args == expr.args[2].args and expr.args[1].is_int(0)): expr = ExprCond( - ExprOp("<=s", *expr.args[0].args), + ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -810,7 +813,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SUB_OF" )): expr = ExprCond( - ExprOp("<s", *expr.args[0].args), + ExprOp(TOK_INF_SIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -821,7 +824,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SIGN_SUB", "FLAG_SUB_OF" )): - expr = ExprOp("<s", *expr.args[0].args) + expr = ExprOp(TOK_INF_SIGNED, *expr.args[0].args) elif (expr.is_op("CC_S<=") and test_cc_eq_args( @@ -830,7 +833,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SUB_OF", "FLAG_EQ_CMP", )): - expr = ExprOp("<=s", *expr.args[0].args) + expr = ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args) elif (expr.is_op("CC_S<=") and len(expr.args) == 3 and @@ -838,7 +841,7 @@ def simp_cc_conds(expr_simp, expr): expr.args[2].is_op("FLAG_EQ_CMP") and expr.args[0].args == expr.args[2].args and expr.args[1].is_int(0)): - expr = ExprOp("<=s", *expr.args[0].args) + expr = ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args) elif (expr.is_op("CC_U<=") and test_cc_eq_args( @@ -846,7 +849,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_SUB_CF", "FLAG_EQ_CMP", )): - expr = ExprOp("<=u", *expr.args[0].args) + expr = ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args) elif (expr.is_op("CC_U>") and test_cc_eq_args( @@ -855,7 +858,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_EQ_CMP", )): expr = ExprCond( - ExprOp("<=u", *expr.args[0].args), + ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args), ExprInt(0, 1), ExprInt(1, 1) ) @@ -867,7 +870,7 @@ def simp_cc_conds(expr_simp, expr): "FLAG_ADD_OF" )): arg0, arg1 = expr.args[0].args - expr = ExprOp("<s", arg0, -arg1) + expr = ExprOp(TOK_INF_SIGNED, arg0, -arg1) return expr @@ -877,12 +880,12 @@ def simp_cond_flag(expr_simp, expr): # FLAG_EQ_CMP(X, Y)?A:B => (X == Y)?A:B cond = expr.cond if cond.is_op("FLAG_EQ_CMP"): - return ExprCond(ExprOp("==", *cond.args), expr.src1, expr.src2) + return ExprCond(ExprOp(TOK_EQUAL, *cond.args), expr.src1, expr.src2) return expr def simp_cond_int(expr_simp, expr): - if (expr.cond.is_op('==') and + if (expr.cond.is_op(TOK_EQUAL) and expr.cond.args[1].is_int() and expr.cond.args[0].is_compose() and len(expr.cond.args[0].args) == 2 and @@ -891,9 +894,20 @@ def simp_cond_int(expr_simp, expr): src = expr.cond.args[0].args[0] int_val = int(expr.cond.args[1]) new_int = ExprInt(int_val, src.size) - expr = expr_simp(ExprCond(ExprOp("==", src, new_int), expr.src1, expr.src2)) + expr = expr_simp( + ExprCond( + ExprOp(TOK_EQUAL, src, new_int), + expr.src1, + expr.src2) + ) elif (expr.cond.is_op() and - expr.cond.op in ['==', '<s', '<=s', '<u', '<=u'] and + expr.cond.op in [ + TOK_EQUAL, + TOK_INF_SIGNED, + TOK_INF_EQUAL_SIGNED, + TOK_INF_UNSIGNED, + TOK_INF_EQUAL_UNSIGNED + ] and expr.cond.args[1].is_int() and expr.cond.args[0].is_op("+") and expr.cond.args[0].args[-1].is_int()): @@ -905,7 +919,12 @@ def simp_cond_int(expr_simp, expr): else: left = ExprOp('+', *left) new_int = expr_simp(right - int_diff) - expr = expr_simp(ExprCond(ExprOp(expr.cond.op, left, new_int), expr.src1, expr.src2)) + expr = expr_simp( + ExprCond( + ExprOp(expr.cond.op, left, new_int), + expr.src1, + expr.src2) + ) return expr @@ -920,7 +939,13 @@ def simp_cmp_int_arg(expr_simp, expr): if not cond.is_op(): return expr op = cond.op - if op not in ['==', '<s', '<=s', '<u', '<=u']: + if op not in [ + TOK_EQUAL, + TOK_INF_SIGNED, + TOK_INF_EQUAL_SIGNED, + TOK_INF_UNSIGNED, + TOK_INF_EQUAL_UNSIGNED + ]: return expr arg1, arg2 = cond.args if arg2.is_int(): @@ -928,19 +953,19 @@ def simp_cmp_int_arg(expr_simp, expr): if not arg1.is_int(): return expr src1, src2 = expr.src1, expr.src2 - if op == "==": - return ExprCond(ExprOp('==', arg2, arg1), src1, src2) + if op == TOK_EQUAL: + return ExprCond(ExprOp(TOK_EQUAL, arg2, arg1), src1, src2) arg1, arg2 = arg2, arg1 src1, src2 = src2, src1 - if op == '<s': - op = '<=s' - elif op == '<=s': - op = '<s' - elif op == '<u': - op = '<=u' - elif op == '<=u': - op = '<u' + if op == TOK_INF_SIGNED: + op = TOK_INF_EQUAL_SIGNED + elif op == TOK_INF_EQUAL_SIGNED: + op = TOK_INF_SIGNED + elif op == TOK_INF_UNSIGNED: + op = TOK_INF_EQUAL_UNSIGNED + elif op == TOK_INF_EQUAL_UNSIGNED: + op = TOK_INF_UNSIGNED return ExprCond(ExprOp(op, arg1, arg2), src1, src2) @@ -1009,7 +1034,7 @@ def simp_double_signext(expr_s, expr): def simp_zeroext_eq_cst(expr_s, expr): # A.zeroExt(X) == int => A == int[:A.size] - if not expr.is_op("=="): + if not expr.is_op(TOK_EQUAL): return expr arg1, arg2 = expr.args if not arg2.is_int(): @@ -1020,4 +1045,16 @@ def simp_zeroext_eq_cst(expr_s, expr): if int(arg2) > (1 << src.size): # Always false return ExprInt(0, 1) - return ExprOp("==", src, ExprInt(int(arg2), src.size)) + return ExprOp(TOK_EQUAL, src, ExprInt(int(arg2), src.size)) + + +def simp_cond_eq_zero(expr_s, expr): + # (X == 0)?(A:B) => X?(B:A) + cond = expr.cond + if not cond.is_op(TOK_EQUAL): + return expr + arg1, arg2 = cond.args + if not arg2.is_int(0): + return expr + new_expr = ExprCond(arg1, expr.src2, expr.src1) + return new_expr diff --git a/miasm2/expression/simplifications_explicit.py b/miasm2/expression/simplifications_explicit.py index 54e9efc2..4c5dde3e 100644 --- a/miasm2/expression/simplifications_explicit.py +++ b/miasm2/expression/simplifications_explicit.py @@ -1,5 +1,6 @@ from miasm2.expression.modint import size2mask -from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose +from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose, \ + TOK_EQUAL def simp_ext(_, expr): @@ -154,5 +155,13 @@ def simp_flags(_, expr): op_nf, = args return ~op_nf + elif expr.is_op(TOK_EQUAL): + arg1, arg2 = args + return ExprCond( + arg1 - arg2, + ExprInt(0, expr.size), + ExprInt(1, expr.size), + ) + return expr diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py index 89a2ac84..6700e826 100644 --- a/miasm2/ir/translators/C.py +++ b/miasm2/ir/translators/C.py @@ -1,6 +1,7 @@ from miasm2.ir.translators.translator import Translator from miasm2.expression.modint import size2mask -from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose +from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose, \ + TOK_EQUAL def int_size_to_bn(value, size): if size < 32: @@ -198,20 +199,14 @@ class TranslatorC(Translator): expr.size, self.from_expr(expr.args[0]), ) - elif expr.op.startswith("sint_to_fp"): - dest_size = expr.size - arg_size = expr.args[0].size - if (arg_size, dest_size) in [ - (32, 32), (64, 64), (32, 64), - ]: - func = "sint%d_to_fp%d" % (arg_size, dest_size) - else: + elif expr.op == "sint_to_fp": + size = expr.size + arg = expr.args[0] + if size not in [32, 64]: raise RuntimeError( - "Unsupported size for sint_to_fp: %r to %r" % ( - arg_size, - dest_size - )) - return "%s(%s)" % (func, self.from_expr(expr.args[0])) + "Unsupported size for sint_to_fp: %r" % size + ) + return "%s_%d(%s)" % (expr.op, size, self.from_expr(arg)) elif expr.op.startswith("fp_to_sint"): dest_size = expr.size arg_size = expr.args[0].size @@ -243,7 +238,7 @@ class TranslatorC(Translator): raise NotImplementedError('Unknown op: %r' % expr.op) elif len(expr.args) == 2: - if expr.op == "==": + if expr.op == TOK_EQUAL: return '(((%s&%s) == (%s&%s))?1:0)' % ( self.from_expr(expr.args[0]), self._size2mask(expr.args[0].size), diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index de5f19df..e7bd004c 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -938,7 +938,7 @@ class LLVMFunction(): self.update_cache(expr, ret) return ret - if op.startswith("sint_to_fp"): + if op == "sint_to_fp": fptype = LLVMType.fptype(expr.size) arg = self.add_ir(expr.args[0]) ret = builder.sitofp(arg, fptype) @@ -946,7 +946,7 @@ class LLVMFunction(): self.update_cache(expr, ret) return ret - if op == "fp_to_sint32": + if op.startswith("fp_to_sint"): size_arg = expr.args[0].size fptype_orig = LLVMType.fptype(size_arg) arg = self.add_ir(expr.args[0]) diff --git a/miasm2/jitter/op_semantics.c b/miasm2/jitter/op_semantics.c index e997226a..c3e11189 100644 --- a/miasm2/jitter/op_semantics.c +++ b/miasm2/jitter/op_semantics.c @@ -755,24 +755,18 @@ unsigned int fpu_fxam_c3(double a) } } -uint64_t sint64_to_fp64(int64_t a) +uint64_t sint_to_fp_64(int64_t a) { double result = (double) a; return *((uint64_t*)&result); } -uint32_t sint32_to_fp32(int32_t a) +uint32_t sint_to_fp_32(int32_t a) { float result = (float) a; return *((uint32_t*)&result); } -uint64_t sint32_to_fp64(int32_t a) -{ - double result = (double) a; - return *((uint64_t*)&result); -} - int32_t fp32_to_sint32(uint32_t a) { // Enforce nearbyint (IEEE-754 behavior) diff --git a/miasm2/jitter/op_semantics.h b/miasm2/jitter/op_semantics.h index 9ff2881e..3d7ca31a 100644 --- a/miasm2/jitter/op_semantics.h +++ b/miasm2/jitter/op_semantics.h @@ -130,9 +130,8 @@ unsigned int fpu_fxam_c1(double a); unsigned int fpu_fxam_c2(double a); unsigned int fpu_fxam_c3(double a); -uint64_t sint64_to_fp64(int64_t a); -uint32_t sint32_to_fp32(int32_t a); -uint64_t sint32_to_fp64(int32_t a); +uint64_t sint_to_fp_64(int64_t a); +uint32_t sint_to_fp_32(int32_t a); int32_t fp32_to_sint32(uint32_t a); int64_t fp64_to_sint64(uint64_t a); int32_t fp64_to_sint32(uint64_t a); diff --git a/test/arch/mep/ir/test_divide.py b/test/arch/mep/ir/test_divide.py index 04d5f6c5..a63d0c5e 100644 --- a/test/arch/mep/ir/test_divide.py +++ b/test/arch/mep/ir/test_divide.py @@ -39,33 +39,21 @@ class TestDivide: exec_instruction("DIV R0, R1", [(ExprId("R0", 32), ExprInt(4, 32)), (ExprId("R1", 32), ExprInt(2, 32))], - [(ExprId("HI", 32), ExprCond(ExprOp("==", - ExprInt(0, 32), - ExprInt(0x80000000, 32)), - ExprInt(0, 32), - ExprInt(0xFFFFFFFC, 32))), - (ExprId("LO", 32), ExprCond(ExprOp("==", - ExprInt(0, 32), - ExprInt(0x80000000, 32)), - ExprInt(2, 32), - ExprInt(0, 32)))]) + [(ExprId("HI", 32), ExprInt(0xFFFFFFFC, 32)), + (ExprId("LO", 32), ExprInt(0, 32))]) # Negative & positive numbers exec_instruction("DIV R0, R1", [(ExprId("R0", 32), ExprInt(-5, 32)), (ExprId("R1", 32), ExprInt(2, 32))], - [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), - ExprInt(1, 32), ExprInt(0xFFFFFFFF, 32))), - (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), - ExprInt(0x7FFFFFFD, 32), ExprInt(0xFFFFFFFE, 32)))]) + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32))]) exec_instruction("DIV R0, R1", [(ExprId("R0", 32), ExprInt(5, 32)), (ExprId("R1", 32), ExprInt(-2, 32))], - [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), - ExprInt(5, 32), ExprInt(0xFFFFFFFF, 32))), - (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)), - ExprInt(0, 32), ExprInt(0xFFFFFFFE, 32)))]) + [(ExprId("HI", 32), ExprInt(0xFFFFFFFF, 32)), + (ExprId("LO", 32), ExprInt(0xFFFFFFFE, 32))]) def test_divu(self): """Test DIVU execution""" diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py index 1d91f109..046c948e 100644 --- a/test/expression/simplifications.py +++ b/test/expression/simplifications.py @@ -479,19 +479,18 @@ to_test = [ (ExprOp_inf_signed(ExprInt(-3, 32), ExprInt(0, 32)), ExprInt(1, 1)), ] -expr_simp_cond = ExpressionSimplifier() -expr_simp_explicit.enable_passes(ExpressionSimplifier.PASS_COND) +expr_simp.enable_passes(ExpressionSimplifier.PASS_COND) for e_input, e_check in to_test: print "#" * 80 - e_check = expr_simp_explicit(e_check) - e_new = expr_simp_explicit(e_input) + e_check = expr_simp(e_check) + e_new = expr_simp(e_input) print "original: ", str(e_input), "new: ", str(e_new) rez = e_new == e_check if not rez: raise ValueError( - 'bug in expr_simp_explicit simp(%s) is %s and should be %s' % (e_input, e_new, e_check)) + 'bug in expr_simp simp(%s) is %s and should be %s' % (e_input, e_new, e_check)) if args.z3: # This check is done on 32 bits, but the size is not use by Miasm formulas, so diff --git a/test/ir/ir2C.py b/test/ir/ir2C.py index 375dedb8..6df439c2 100755 --- a/test/ir/ir2C.py +++ b/test/ir/ir2C.py @@ -2,7 +2,7 @@ #-*- coding:utf-8 -*- import unittest - +from miasm2.expression.expression import TOK_EQUAL class TestIrIr2C(unittest.TestCase): @@ -32,7 +32,7 @@ class TestIrIr2C(unittest.TestCase): # Binary operators self.translationTest( - ExprOp('==', *args[:2]), r'(((0x0&0xffffffff) == (0x1&0xffffffff))?1:0)') + ExprOp(TOK_EQUAL, *args[:2]), r'(((0x0&0xffffffff) == (0x1&0xffffffff))?1:0)') self.translationTest( ExprOp('%', *args[:2]), r'(((0x0&0xffffffff)%(0x1&0xffffffff))&0xffffffff)') self.translationTest( |