def test_sbvck3(self): """Test SBVCK3 execution""" # SBVCK3 R0,Rn,Rm exec_instruction( "SBVCK3 R0, R1, R2", [(ExprId("R1", 32), ExprInt(2, 32)), (ExprId("R2", 32), ExprInt(1, 32))], [(ExprId("R0", 32), ExprCond( ExprOp( ">", ExprInt(3, 32), ExprCond(ExprOp(">", ExprInt(0x2, 32), ExprInt(0x1, 32)), ExprInt(0x2, 32), ExprInt(0x1, 32))), ExprInt(1, 32), ExprInt(0, 32)))]) exec_instruction( "SBVCK3 R0, R1, R2", [(ExprId("R1", 32), ExprInt(0, 32)), (ExprId("R2", 32), ExprInt(1, 32))], [(ExprId("R0", 32), ExprCond( ExprOp( ">", ExprInt(1, 32), ExprCond(ExprOp(">", ExprInt(0, 32), ExprInt(1, 32)), ExprInt(0, 32), ExprInt(1, 32))), ExprInt( 1, 32), ExprInt(0, 32)))])
def simp_cmp_int_arg(_, expr): """ (0x10 <= R0) ? A:B => (R0 < 0x10) ? B:A """ cond = expr.cond if not cond.is_op(): return expr op = cond.op 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(): return expr if not arg1.is_int(): return expr src1, src2 = expr.src1, expr.src2 if op == TOK_EQUAL: return ExprCond(ExprOp(TOK_EQUAL, arg2, arg1), src1, src2) arg1, arg2 = arg2, arg1 src1, src2 = src2, src1 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)
def simp_cond(_, expr): """ Common simplifications on ExprCond. Eval exprcond src1/src2 with satifiable/unsatisfiable condition propagation """ if (not expr.cond.is_int()) and expr.cond.size == 1: src1 = expr.src1.replace_expr({expr.cond: ExprInt(1, 1)}) src2 = expr.src2.replace_expr({expr.cond: ExprInt(0, 1)}) if src1 != expr.src1 or src2 != expr.src2: return ExprCond(expr.cond, src1, src2) # -A ? B:C => A ? B:C if expr.cond.is_op('-') and len(expr.cond.args) == 1: expr = ExprCond(expr.cond.args[0], expr.src1, expr.src2) # a?x:x elif expr.src1 == expr.src2: expr = expr.src1 # int ? A:B => A or B elif expr.cond.is_int(): if expr.cond.arg == 0: expr = expr.src2 else: expr = expr.src1 # a?(a?b:c):x => a?b:x elif expr.src1.is_cond() and expr.cond == expr.src1.cond: expr = ExprCond(expr.cond, expr.src1.src1, expr.src2) # a?x:(a?b:c) => a?x:c elif expr.src2.is_cond() and expr.cond == expr.src2.cond: expr = ExprCond(expr.cond, expr.src1, expr.src2.src2) # a|int ? b:c => b with int != 0 elif (expr.cond.is_op('|') and expr.cond.args[1].is_int() and expr.cond.args[1].arg != 0): return expr.src1 # (C?int1:int2)?(A:B) => elif (expr.cond.is_cond() and expr.cond.src1.is_int() and expr.cond.src2.is_int()): int1 = expr.cond.src1.arg.arg int2 = expr.cond.src2.arg.arg if int1 and int2: expr = expr.src1 elif int1 == 0 and int2 == 0: expr = expr.src2 elif int1 == 0 and int2: expr = ExprCond(expr.cond.cond, expr.src2, expr.src1) elif int1 and int2 == 0: expr = ExprCond(expr.cond.cond, expr.src1, expr.src2) elif expr.cond.is_compose(): # {0, X, 0}?(A:B) => X?(A:B) args = [arg for arg in expr.cond.args if not arg.is_int(0)] if len(args) == 1: arg = args.pop() return ExprCond(arg, expr.src1, expr.src2) elif len(args) < len(expr.cond.args): return ExprCond(ExprCompose(*args), expr.src1, expr.src2) return expr
def eval_exprcond(self, expr, **kwargs): """[DEV]: Evaluate an ExprCond using the current state""" cond = self.eval_expr_visitor(expr.cond, **kwargs) src1 = self.eval_expr_visitor(expr.src1, **kwargs) src2 = self.eval_expr_visitor(expr.src2, **kwargs) ret = ExprCond(cond, src1, src2) return ret
def simp_cond_logic_ext(expr_s, expr): """(X.zeroExt() + ... + Int) ? A:B => X + ... + int[:] ? A:B""" cond = expr.cond if not cond.is_op(): return expr if cond.op not in ["&", "^", "|"]: return expr is_ok = True sizes = set() for arg in cond.args: if arg.is_int(): continue if (arg.is_op() and arg.op.startswith("zeroExt")): sizes.add(arg.args[0].size) continue is_ok = False break if not is_ok: return expr if len(sizes) != 1: return expr size = list(sizes)[0] args = [expr_s(arg[:size]) for arg in cond.args] cond = ExprOp(cond.op, *args) return ExprCond(cond, expr.src1, expr.src2)
def simp_cond_op_int(_, expr): "Extract conditions from operations" # x?a:b + x?c:d + e => x?(a+c+e:b+d+e) if not expr.op in ["+", "|", "^", "&", "*", '<<', '>>', 'a>>']: return expr if len(expr.args) < 2: return expr conds = set() for arg in expr.args: if arg.is_cond(): conds.add(arg) if len(conds) != 1: return expr cond = list(conds).pop() args1, args2 = [], [] for arg in expr.args: if arg.is_cond(): args1.append(arg.src1) args2.append(arg.src2) else: args1.append(arg) args2.append(arg) return ExprCond(cond.cond, ExprOp(expr.op, *args1), ExprOp(expr.op, *args2))
def csinc(ir, instr, arg1, arg2, arg3, arg4): e = [] cond_expr = cond2expr[arg4.name] e.append( ExprAssign(arg1, ExprCond(cond_expr, arg2, arg3 + ExprInt(1, arg3.size)))) return e, []
def recoverAlgorithm(self): if self.normalIRCFG is None: self.getNormalIRCFG() newLocDB = LocationDB() size = BinaryAnalysis.disasmEngine.attrib newIRA = BinaryAnalysis.iraType(newLocDB) newIRCFG = newIRA.new_ircfg() numLockey = 0 head = LocKey(numLockey) todo = [(self.address, head, {}, None)] numLockey += 1 while todo: nextTarget, lockey, state, preBlock = todo.pop() nextTarget, state = self.symbolicExecution(self.normalIRA, self.normalIRCFG, nextTarget, state) if isinstance(nextTarget, ExprCond): newLockey1 = LocKey(numLockey) newLockey2 = LocKey(numLockey + 1) ir_dst = state[newIRCFG.IRDst] new_cond = ExprCond(ir_dst.cond, ExprLoc(newLockey1, size), ExprLoc(newLockey2, size)) state[newIRCFG.IRDst] = new_cond numLockey += 2 newIRBlock = self.addIRBlock(newIRCFG, state, lockey) state[newIRCFG.IRDst] = ir_dst todo.append((nextTarget.src1, newLockey1, state, newIRBlock)) todo.append((nextTarget.src2, newLockey2, state, newIRBlock)) else: self.addIRBlock(newIRCFG, state, lockey) return newLocDB, newIRCFG
def from_ExprOp(self, expr): if expr.op in self.op_no_translate: args = list(map(self.from_expr, expr.args)) if len(expr.args) == 1: return "((%s %s) & 0x%x)" % (expr.op, args[0], (1 << expr.size) - 1) else: return "((%s) & 0x%x)" % ((" %s " % expr.op).join(args), (1 << expr.size) - 1) elif expr.op == "parity": return "(%s & 0x1)" % self.from_expr(expr.args[0]) elif expr.op == "==": return self.from_expr( ExprCond(expr.args[0] - expr.args[1], ExprInt(0, 1), ExprInt(1, 1))) elif expr.op in ["<<<", ">>>"]: amount_raw = expr.args[1] amount = expr.args[1] % ExprInt(amount_raw.size, expr.size) amount_inv = ExprInt(expr.size, expr.size) - amount if expr.op == "<<<": amount, amount_inv = amount_inv, amount part1 = "(%s >> %s)" % (self.from_expr( expr.args[0]), self.from_expr(amount)) part2 = "(%s << %s)" % (self.from_expr( expr.args[0]), self.from_expr(amount_inv)) return "((%s | %s) &0x%x)" % (part1, part2, int(expr.mask)) raise NotImplementedError("Unknown operator: %s" % expr.op)
def sbvck3(ir, instr, r0, rn, rm): """SBVCK3 - Check subtraction overflow""" # if(Overflow(Rn-Rm)) R0<-1 else R0<-0 (Signed) # Subtract registers reg_sub = ExprOp("+", rn, rm) # Get the register storing the highest value max_rn_rm = ExprCond(ExprOp(">", rn, rm), rn, rm) # Check for an overflow overflow_test = ExprOp(">", reg_sub, max_rn_rm) # Return the result condition = ExprCond(overflow_test, ExprInt(1, 32), ExprInt(0, 32)) return [ExprAssign(r0, condition)], []
def cset(ir, instr, arg1, arg2): e = [] cond_expr = cond2expr[arg2.name] e.append( ExprAssign( arg1, ExprCond(cond_expr, ExprInt(1, arg1.size), ExprInt(0, arg1.size)))) return e, []
def eval_exprcond(self, expr, **kwargs): """[DEV]: Evaluate an ExprCond using the current state""" cond = self.eval_expr_visitor(expr.cond, **kwargs) src1 = self.eval_expr_visitor(expr.src1, **kwargs) src2 = self.eval_expr_visitor(expr.src2, **kwargs) if cond.is_id(TOPSTR) or src1.is_id(TOPSTR) or src2.is_id(TOPSTR): ret = exprid_top(expr) else: ret = ExprCond(cond, src1, src2) return ret
def simp_cond_eq_zero(_, 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
def categorize(self, node, lvl=0, **kwargs): """Recursively apply rules to @node @node: ExprNode to analyze @lvl: actual recursion level """ expr = node.expr log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr) if isinstance(expr, ExprId): node = ExprNodeId(expr) elif isinstance(expr, ExprInt): node = ExprNodeInt(expr) elif isinstance(expr, ExprLoc): node = ExprNodeLoc(expr) elif isinstance(expr, ExprMem): ptr = self.categorize(node.ptr, lvl=lvl + 1, **kwargs) node = ExprNodeMem(ExprMem(ptr.expr, expr.size)) node.ptr = ptr elif isinstance(expr, ExprSlice): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) node = ExprNodeSlice(ExprSlice(arg.expr, expr.start, expr.stop)) node.arg = arg elif isinstance(expr, ExprOp): new_args = [] for arg in node.args: new_a = self.categorize(arg, lvl=lvl + 1, **kwargs) assert new_a.expr.size == arg.expr.size new_args.append(new_a) node = ExprNodeOp(ExprOp(expr.op, *[x.expr for x in new_args])) node.args = new_args expr = node.expr elif isinstance(expr, ExprCompose): new_args = [] new_expr_args = [] for arg in node.args: arg = self.categorize(arg, lvl=lvl + 1, **kwargs) new_args.append(arg) new_expr_args.append(arg.expr) new_expr = ExprCompose(*new_expr_args) node = ExprNodeCompose(new_expr) node.args = new_args elif isinstance(expr, ExprCond): cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs) src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs) src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs) node = ExprNodeCond(ExprCond(cond.expr, src1.expr, src2.expr)) node.cond, node.src1, node.src2 = cond, src1, src2 else: raise TypeError("Unknown Expr Type %r", type(expr)) node.info = self.apply_rules(node, lvl=lvl, **kwargs) log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr, node.info) return node
def simp_mem(_, expr): """ Common simplifications on ExprMem: @32[x?a:b] => x?@32[a]:@32[b] """ if expr.ptr.is_cond(): cond = expr.ptr ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size), ExprMem(cond.src2, expr.size)) return ret return expr
def simp_cond_zeroext(_, expr): """ X.zeroExt()?(A:B) => X ? A:B X.signExt()?(A:B) => X ? A:B """ if not (expr.cond.is_op() and (expr.cond.op.startswith("zeroExt") or expr.cond.op.startswith("signExt"))): return expr ret = ExprCond(expr.cond.args[0], expr.src1, expr.src2) return ret
def ccmp(ir, instr, arg1, arg2, arg3, arg4): e = [] if (arg2.is_int()): arg2 = ExprInt(int(arg2), arg1.size) default_nf = arg3[0:1] default_zf = arg3[1:2] default_cf = arg3[2:3] default_of = arg3[3:4] cond_expr = cond2expr[arg4.name] res = arg1 - arg2 new_nf = nf new_zf = update_flag_zf(res)[0].src new_cf = update_flag_sub_cf(arg1, arg2)[0].src new_of = update_flag_sub_of(arg1, arg2)[0].src e.append(ExprAssign(nf, ExprCond(cond_expr, new_nf, default_nf))) e.append(ExprAssign(zf, ExprCond(cond_expr, new_zf, default_zf))) e.append(ExprAssign(cf, ExprCond(cond_expr, new_cf, default_cf))) e.append(ExprAssign(of, ExprCond(cond_expr, new_of, default_of))) return e, []
def from_ExprCond(self, expr: Expr) -> Expr: """ Translates an ExprCond. Args: expr: Expression to translate. Returns: Expression as ExprCond. """ return ExprCond(self.from_expr(expr.cond), self.from_expr(expr.src1), self.from_expr(expr.src2))
def simp_compose(e_s, expr): "Commons simplification on ExprCompose" args = merge_sliceto_slice(expr) out = [] # compose of compose for arg in args: if arg.is_compose(): out += arg.args else: out.append(arg) args = out # Compose(a) with a.size = compose.size => a if len(args) == 1 and args[0].size == expr.size: return args[0] # {(X[z:], 0, X.size-z), (0, X.size-z, X.size)} => (X >> z) if len(args) == 2 and args[1].is_int(0): if (args[0].is_slice() and args[0].stop == args[0].arg.size and args[0].size + args[1].size == args[0].arg.size): new_expr = args[0].arg >> ExprInt(args[0].start, args[0].arg.size) return new_expr # {@X[base + i] 0 X, @Y[base + i + X] X (X + Y)} => @(X+Y)[base + i] for i, arg in enumerate(args[:-1]): nxt = args[i + 1] if arg.is_mem() and nxt.is_mem(): gap = e_s(nxt.ptr - arg.ptr) if gap.is_int() and arg.size % 8 == 0 and int( gap) == arg.size // 8: args = args[:i] + [ExprMem(arg.ptr, arg.size + nxt.size) ] + args[i + 2:] return ExprCompose(*args) # {a, x?b:d, x?c:e, f} => x?{a, b, c, f}:{a, d, e, f} conds = set(arg.cond for arg in expr.args if arg.is_cond()) if len(conds) == 1: cond = list(conds)[0] args1, args2 = [], [] for arg in expr.args: if arg.is_cond(): args1.append(arg.src1) args2.append(arg.src2) else: args1.append(arg) args2.append(arg) arg1 = e_s(ExprCompose(*args1)) arg2 = e_s(ExprCompose(*args2)) return ExprCond(cond, arg1, arg2) return ExprCompose(*args)
def simp_cond_sign_bit(_, expr): """(a & .. & 0x80000000) ? A:B => (a & ...) <s 0 ? A:B""" cond = expr.cond if not cond.is_op('&'): return expr last = cond.args[-1] if not last.is_int(1 << (last.size - 1)): return expr zero = ExprInt(0, expr.cond.size) if len(cond.args) == 2: args = [cond.args[0], zero] else: args = [ExprOp('&', *list(cond.args[:-1])), zero] cond = ExprOp(TOK_INF_SIGNED, *args) return ExprCond(cond, expr.src1, expr.src2)
def simp_ext(_, expr): if expr.op.startswith('zeroExt_'): arg = expr.args[0] if expr.size == arg.size: return arg return ExprCompose(arg, ExprInt(0, expr.size - arg.size)) if expr.op.startswith("signExt_"): arg = expr.args[0] add_size = expr.size - arg.size new_expr = ExprCompose( arg, ExprCond(arg.msb(), ExprInt(size2mask(add_size), add_size), ExprInt(0, add_size))) return new_expr return expr
def div(rn, rm): """DIV - Signed division""" # LO <- Rn / Rm, HI <- Rn % Rm (Signed) # Mask sign bits sign_mask = i32(0x80000000) sign_rn = rn & sign_mask sign_rm = rm & sign_mask # Check if both numbers are positive or negative are_both_neg = sign_rn & sign_rm 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) rm_inv = ~rm + i32(1) # Used to delay the arithmetic computations tmp_rm = rm if rm else i32(1) tmp_rm_inv = rm_inv if rm_inv else i32(1) # Results if only rn, or rm is negative LO_rn_neg = (~(rn_inv // tmp_rm) + i32(1)) if sign_rn else (~(rn // tmp_rm_inv) + i32(1)) HI_rn_neg = (~(rn_inv % tmp_rm) + i32(1)) if sign_rn else (~(rn % tmp_rm_inv) + i32(1)) # Results if both numbers are positive LO_pos = rn // tmp_rm if are_both_pos else LO_rn_neg HI_pos = rn % tmp_rm if are_both_pos else HI_rn_neg # Results if both numbers are negative LO_neg = rn_inv // tmp_rm_inv if are_both_neg else LO_pos HI_neg = rn_inv % tmp_rm_inv if are_both_neg else HI_pos # Results if rm is equal to zero LO = LO_neg if rm else LO HI = HI_neg if rm else HI exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO)
def simp_cond_factor(e_s, expr): "Merge similar conditions" if not expr.op in ["+", "|", "^", "&", "*", '<<', '>>', 'a>>']: return expr if len(expr.args) < 2: return expr if expr.op in ['>>', '<<', 'a>>']: assert len(expr.args) == 2 # Note: the following code is correct for non-commutative operation only if # there is 2 arguments. Otherwise, the order is not conserved # Regroup sub-expression by similar conditions conds = {} not_conds = [] multi_cond = False for arg in expr.args: if not arg.is_cond(): not_conds.append(arg) continue cond = arg.cond if not cond in conds: conds[cond] = [] else: multi_cond = True conds[cond].append(arg) if not multi_cond: return expr # Rebuild the new expression c_out = not_conds for cond, vals in viewitems(conds): new_src1 = [x.src1 for x in vals] new_src2 = [x.src2 for x in vals] src1 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src1)) src2 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src2)) c_out.append(ExprCond(cond, src1, src2)) if len(c_out) == 1: new_e = c_out[0] else: new_e = ExprOp(expr.op, *c_out) return new_e
def simp_x_and_cst_eq_cst(_, expr): """ (x & ... & onebitmask == onebitmask) ? A:B => (x & ... & onebitmask) ? A:B """ cond = expr.cond if not cond.is_op(TOK_EQUAL): return expr arg1, mask2 = cond.args if not mask2.is_int(): return expr if not test_one_bit_set(int(mask2)): return expr if not arg1.is_op('&'): return expr mask1 = arg1.args[-1] if mask1 != mask2: return expr cond = ExprOp('&', *arg1.args) return ExprCond(cond, expr.src1, expr.src2)
def simp_cond_add(expr_s, expr): """ (a+b)?X:Y => (a == b)?Y:X (a^b)?X:Y => (a == b)?Y:X """ cond = expr.cond if not cond.is_op(): return expr if cond.op not in ['+', '^']: return expr if len(cond.args) != 2: return expr arg1, arg2 = cond.args if cond.is_op('+'): new_cond = ExprOp('==', arg1, expr_s(-arg2)) elif cond.is_op('^'): new_cond = ExprOp('==', arg1, arg2) else: raise ValueError('Bad case') return ExprCond(new_cond, expr.src2, expr.src1)
def casp(ir, instr, arg1, arg2, arg3): # XXX TODO: memory barrier e = [] if arg1.size == 32: regs = gpregs32_expr else: regs = gpregs64_expr index1 = regs.index(arg1) index2 = regs.index(arg2) # TODO endianness comp_value = ExprCompose(regs[index1], regs[index1 + 1]) new_value = ExprCompose(regs[index2], regs[index2 + 1]) assert arg3.is_op('preinc') ptr = arg3.args[0] data = ExprMem(ptr, comp_value.size) loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e.append( ExprAssign( ir.IRDst, ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do, loc_store))) e_store = [] e_store.append(ExprAssign(data, new_value)) e_store.append(ExprAssign(ir.IRDst, loc_do)) blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)]) e_do = [] e_do.append(ExprAssign(regs[index1], data[:data.size // 2])) e_do.append(ExprAssign(regs[index1 + 1], data[data.size // 2:])) e_do.append(ExprAssign(ir.IRDst, loc_next)) blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)]) return e, [blk_store, blk_do]
def call_effects(self, ad, instr): call_assignblk = AssignBlock([ ExprAssign( self.ret_reg, ExprOp( 'call_func_ret', ad, self.arch.regs.R0, self.arch.regs.R1, self.arch.regs.R2, self.arch.regs.R3, )), ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], instr) cond = instr.additional_info.cond if cond == 14: # COND_ALWAYS: return [call_assignblk], [] # Call is a conditional instruction cond = tab_cond[cond] loc_next = self.get_next_loc_key(instr) loc_next_expr = ExprLoc(loc_next, 32) loc_do = self.loc_db.add_location() loc_do_expr = ExprLoc(loc_do, 32) dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr) call_assignblks = [ call_assignblk, AssignBlock([ExprAssign(self.IRDst, loc_next_expr)], instr), ] e_do = IRBlock(loc_do, call_assignblks) assignblks_out = [ AssignBlock([ExprAssign(self.IRDst, dst_cond)], instr) ] return assignblks_out, [e_do]
def csneg(ir, instr, arg1, arg2, arg3, arg4): e = [] cond_expr = cond2expr[arg4.name] e.append(ExprAssign(arg1, ExprCond(cond_expr, arg2, -arg3))) return e, []
""" out.add(r) return out IRA = IRATest(loc_db) END = ExprId("END", IRDst.size) G0_IRA = IRA.new_ircfg() G0_IRB0 = gen_irblock( LBL0, [[ExprAssign(a, CST1)], [ExprAssign(IRDst, ExprLoc(LBL1, 32))]]) G0_IRB1 = gen_irblock( LBL1, [[ExprAssign(a, a + CST1)], [ExprAssign(IRDst, ExprCond(x, ExprLoc(LBL1, 32), ExprLoc(LBL2, 32)))]]) G0_IRB2 = gen_irblock(LBL2, [[ExprAssign(r, a)], [ExprAssign(IRDst, END)]]) for irb in [G0_IRB0, G0_IRB1, G0_IRB2]: G0_IRA.add_irblock(irb) G1_IRA = IRA.new_ircfg() G1_IRB0 = gen_irblock( LBL0, [[ExprAssign(a, CST1)], [ExprAssign(IRDst, ExprCond(x, ExprLoc(LBL1, 32), ExprLoc(LBL2, 32)))]]) G1_IRB1 = gen_irblock( LBL1, [[ExprAssign(a, a + CST1)], [ExprAssign(IRDst, ExprLoc(LBL3, 32))]]) G1_IRB2 = gen_irblock( LBL2, [[ExprAssign(a, a + CST2)], [ExprAssign(IRDst, ExprLoc(LBL3, 32))]])
def simp_cond_flag(_, 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(TOK_EQUAL, *cond.args), expr.src1, expr.src2) return expr