def _(term, smt): x = smt.eval(term.x) with smt.local_nonpoison() as ny: y = smt.eval(term.y) smt.add_defs(y != 0, *ny) if 'exact' in term.flags: smt.add_nonpoison(z3.UDiv(x,y)*y == x) return z3.UDiv(x,y)
def udiv(self, ctx, return_type, a, atype, b, btype, nuw=False, nsw=False, exact=False): assert atype == return_type assert atype == btype assert not nuw and not nsw and not exact assert util.path_condition_implies( ctx, b != z3.BitVecVal(0, btype.size()), print_model=True), "udiv by zero" return z3.UDiv(a, b)
def UDiv(self, other): if isinstance(other, int): other = BVV(other, self.size) else: assert isinstance(other, BV) assert self.size == other.size return BVExpr(self.size, z3.UDiv(self.z3obj, other.z3obj), self.interval.UDiv(other.interval))
def sys_map_pcipage(old, pt, index, pcipn, perm): cond = z3.And( # pt is a valid PT page is_pn_valid(pt), old.pages[pt].type == dt.page_type.PAGE_TYPE_X86_PT, old.pages[pt].owner == old.current, z3.ULT(index, 512), # pcipn is a valid pci page owned by current is_pcipn_valid(pcipn), old.pcipages[pcipn].valid, old.pci[old.pcipages[pcipn].owner].owner == old.current, # perm has no unsafe bits on it and it is present perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, perm & dt.PTE_P != 0, # slot should be empty old.pages[pt].data(index) & dt.PTE_P == 0, ) new = old.copy() new.pages[pt].data[index] = ((z3.UDiv( dt.PCI_START, util.i64(dt.PAGE_SIZE)) + pcipn) << dt.PTE_PFN_SHIFT) | perm # maintain the "shadow" pgtable new.pages[pt].pgtable_pn[index] = pcipn new.pages[pt].pgtable_perm[index] = perm new.pages[pt].pgtable_type[index] = dt.PGTYPE_PCIPAGE new.flush_tlb(old.current) return cond, util.If(cond, new, old)
def from_ExprOp(self, expr): args = map(self.from_expr, expr.args) res = args[0] if len(args) > 1: for arg in args[1:]: if expr.op in self.trivial_ops: res = eval("res %s arg" % expr.op) elif expr.op == ">>": res = z3.LShR(res, arg) elif expr.op == "a>>": res = res >> arg elif expr.op == "<<<": res = z3.RotateLeft(res, arg) elif expr.op == ">>>": res = z3.RotateRight(res, arg) elif expr.op == "idiv": res = self._idivC(res, arg) elif expr.op == "udiv": res = z3.UDiv(res, arg) elif expr.op == "imod": res = res - (arg * (self._idivC(res, arg))) elif expr.op == "umod": res = z3.URem(res, arg) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) elif expr.op == 'parity': arg = z3.Extract(7, 0, res) res = z3.BitVecVal(1, 1) for i in xrange(8): res = res ^ z3.Extract(i, i, arg) elif expr.op == '-': res = -res elif expr.op == "cnttrailzeros": size = expr.size src = res res = z3.If(src == 0, size, src) for i in xrange(size - 1, -1, -1): res = z3.If((src & (1 << i)) != 0, i, res) elif expr.op == "cntleadzeros": size = expr.size src = res res = z3.If(src == 0, size, src) for i in xrange(size, 0, -1): index = -i % size out = size - (index + 1) res = z3.If((src & (1 << index)) != 0, out, res) elif expr.op.startswith("zeroExt"): arg, = expr.args res = z3.ZeroExt(expr.size - arg.size, self.from_expr(arg)) elif expr.op.startswith("signExt"): arg, = expr.args res = z3.SignExt(expr.size - arg.size, self.from_expr(arg)) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) return res
def UDiv(a: BitVec, b: BitVec) -> BitVec: """Create an unsigned division expression. :param a: :param b: :return: """ union = a.annotations + b.annotations return BitVec(z3.UDiv(a.raw, b.raw), annotations=union)
def DIV(self, gstate, a, b): a, b = map(svm_utils.convert_to_bitvec, (a, b)) if self.svm.abs_div and not svm_utils.is_bv_concrete(a) and not svm_utils.is_bv_concrete(b): abs_bv = self.svm.sym_bv_generator.get_sym_bitvec(constraints.ConstraintType.DIV, gstate.wstate.gen, unique=True) gstate.mstate.stack.append(abs_bv) else: gstate.mstate.stack.append(z3.UDiv(a, b))
def UDiv(self, other): if isinstance(other, int): other = BVV(other, self.size) else: assert isinstance(other, BV) assert self.size == other.size if isinstance(other, BVV): return BVV((self.value // other.value) & self._mask, self.size) return BVExpr(self.size, z3.UDiv(self.z3obj, other.z3obj), self.interval.UDiv(other.interval))
def _idivC(self, num, den): """Divide (signed) @num by @den (z3 values) as C would See modint.__div__ for implementation choice """ result_sign = z3.If(num * den >= 0, z3.BitVecVal(1, num.size()), z3.BitVecVal(-1, num.size()), ) return z3.UDiv(self._abs(num), self._abs(den)) * result_sign
def alloc_page_table(old, pid, frm, index, to, perm, from_type, to_type): cond = z3.And( # The to argument is a valid page and is marked as free is_pn_valid(to), old.pages[to].type == dt.page_type.PAGE_TYPE_FREE, # The pid is valid and is either current running process or child embryo is_pid_valid(pid), z3.Or(pid == old.current, z3.And( old.procs[pid].ppid == old.current, old.procs[pid].state == dt.proc_state.PROC_EMBRYO)), # The from parameter is valid and of type PML4 and owned by pid is_pn_valid(frm), old.pages[frm].owner == pid, old.pages[frm].type == from_type, # Index is a valid page index z3.ULT(index, 512), # perm has no unsafe bits on it and it is present perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, perm & dt.PTE_P != 0, # index does not have the P bit in PML4 old.pages[frm].data(index) & dt.PTE_P == 0, ) new = old.copy() new.pages[to].owner = pid new.pages[to].type = to_type new.pages[frm].data[index] = ( (z3.UDiv(new.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + to) << dt.PTE_PFN_SHIFT) | perm # Zero out the new page new.pages[to].data = util.i64(0) # Maintain the "shadow" pgtable new.pages[frm].pgtable_pn[index] = to new.pages[to].pgtable_reverse_pn = frm new.pages[to].pgtable_reverse_idx = index new.pages[frm].pgtable_perm[index] = perm new.pages[frm].pgtable_type[index] = dt.PGTYPE_PAGE new.pages[to].pgtable_pn = util.i64(0) new.pages[to].pgtable_perm = util.i64(0) new.pages[to].pgtable_type = dt.PGTYPE_NONE new.procs[pid].nr_pages[to] += 1 new.flush_tlb(pid) return cond, util.If(cond, new, old)
def ast_to_z3_expression(ast: Union[AstNode, AstLeaf], use_bitvecval=False): if not Z3_INSTALLED: raise D810Z3Exception("Z3 is not installed") if isinstance(ast, AstLeaf): if ast.is_constant(): return z3.BitVecVal(ast.value, 32) return ast.z3_var if ast.opcode == m_neg: return -(ast_to_z3_expression(ast.left, use_bitvecval)) elif ast.opcode == m_lnot: return not (ast_to_z3_expression(ast.left, use_bitvecval)) elif ast.opcode == m_bnot: return ~(ast_to_z3_expression(ast.left, use_bitvecval)) elif ast.opcode == m_add: return (ast_to_z3_expression(ast.left, use_bitvecval)) + ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_sub: return (ast_to_z3_expression(ast.left, use_bitvecval)) - ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_mul: return (ast_to_z3_expression(ast.left, use_bitvecval)) * ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_udiv: return z3.UDiv(ast_to_z3_expression(ast.left, use_bitvecval=True), ast_to_z3_expression(ast.right, use_bitvecval=True)) elif ast.opcode == m_sdiv: return (ast_to_z3_expression(ast.left, use_bitvecval)) / ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_umod: return z3.URem(ast_to_z3_expression(ast.left, use_bitvecval), ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_smod: return (ast_to_z3_expression(ast.left, use_bitvecval)) % ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_or: return (ast_to_z3_expression(ast.left, use_bitvecval)) | (ast_to_z3_expression( ast.right, use_bitvecval)) elif ast.opcode == m_and: return (ast_to_z3_expression(ast.left, use_bitvecval)) & ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_xor: return (ast_to_z3_expression(ast.left, use_bitvecval)) ^ ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_shl: return (ast_to_z3_expression(ast.left, use_bitvecval)) << ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_shr: return z3.LShR(ast_to_z3_expression(ast.left, use_bitvecval), ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode == m_sar: return (ast_to_z3_expression(ast.left, use_bitvecval)) >> ( ast_to_z3_expression(ast.right, use_bitvecval)) elif ast.opcode in [m_xdu, m_xds, m_low, m_high]: return ast_to_z3_expression(ast.left, use_bitvecval) raise D810Z3Exception("Z3 evaluation: Unknown opcode {0} for {1}".format( opcode_to_string(ast.opcode), ast))
def sys_map_page(old, pid, frm, index, pa, perm, from_type): pfn = z3.UDiv(pa, util.i64(dt.PAGE_SIZE)) n = pfn - z3.UDiv(old.page_desc_table_ptr_to_int, util.i64(dt.PAGE_SIZE)) cond = z3.And( is_pid_valid(pid), # the pid is either current or an embryo belonging to current z3.Or(pid == old.current, z3.And( old.procs[pid].ppid == old.current, old.procs[pid].state == dt.proc_state.PROC_EMBRYO)), # frm is a valid pn of type PT whose owner is pid is_pn_valid(frm), old.pages[frm].type == from_type, old.pages[frm].owner == pid, # Index is a valid page index z3.ULT(index, 512), # perm has no unsafe bits on it and it is present and non-writable perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, perm & dt.PTE_P != 0, # index does not have the P bit in the from page old.pages[frm].data(index) & dt.PTE_P == 0, ) new = old.copy() new.pages[frm].data[index] = ((z3.UDiv( new.page_desc_table_ptr_to_int, util.i64(dt.PAGE_SIZE)) + n) << dt.PTE_PFN_SHIFT) | perm # maintain the "shadow" pgtable new.pages[frm].pgtable_pn[index] = n new.pages[frm].pgtable_perm[index] = perm new.pages[frm].pgtable_type[index] = dt.PGTYPE_PAGE_DESC new.flush_tlb(pid) return cond, util.If(cond, new, old)
def pgentry2pfn(ks, off, perm, type): res = util.i64(0) res = util.If(type == dt.PGTYPE_PCIPAGE, util.i64(dt.PCI_START), res) res = util.If(type == dt.PGTYPE_IOMMU_FRAME, ks.dmapages_ptr_to_int, res) res = util.If(type == dt.PGTYPE_DEVICES, ks.devices_ptr_to_int, res) res = util.If(type == dt.PGTYPE_FILE_TABLE, ks.file_table_ptr_to_int, res) res = util.If(type == dt.PGTYPE_PAGE_DESC, ks.page_desc_table_ptr_to_int, res) res = util.If(type == dt.PGTYPE_PROC, ks.proc_table_ptr_to_int, res) res = util.If(type == dt.PGTYPE_PAGE, ks.pages_ptr_to_int, res) return ((z3.UDiv(res, util.i64(dt.PAGE_SIZE)) + off) << dt.PTE_PFN_SHIFT) | perm
def sys_ack_intr(old, vector): cond = z3.BoolVal(True) new = old.copy() vector = z3.ZeroExt(64 - vector.size(), vector) idx = z3.UDiv(vector, 64) mask = 1 << (vector % 64) new.procs[new.current].intr[idx] = new.procs[new.current].intr(idx) & ~mask return cond, new
def from_ExprOp(self, expr): args = map(self.from_expr, expr.args) res = args[0] if len(args) > 1: for arg in args[1:]: if expr.op in self.trivial_ops: res = eval("res %s arg" % expr.op) elif expr.op == ">>": res = z3.LShR(res, arg) elif expr.op == "a>>": res = res >> arg elif expr.op == "a<<": res = res << arg elif expr.op == "<<<": res = z3.RotateLeft(res, arg) elif expr.op == ">>>": res = z3.RotateRight(res, arg) elif expr.op == "idiv": res = res / arg elif expr.op == "udiv": res = z3.UDiv(res, arg) elif expr.op == "imod": res = res % arg elif expr.op == "umod": res = z3.URem(res, arg) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) elif expr.op == 'parity': arg = z3.Extract(7, 0, res) res = z3.BitVecVal(1, 1) for i in xrange(8): res = res ^ z3.Extract(i, i, arg) elif expr.op == '-': res = -res elif expr.op == "bsf": size = expr.size src = res res = z3.If((src & (1 << (size - 1))) != 0, size - 1, src) for i in xrange(size - 2, -1, -1): res = z3.If((src & (1 << i)) != 0, i, res) elif expr.op == "bsr": size = expr.size src = res res = z3.If((src & 1) != 0, 0, src) for i in xrange(size - 1, 0, -1): index = -i % size res = z3.If((src & (1 << index)) != 0, index, res) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) return res
def sys_protect_frame(old, pt, index, frame, perm): cond = z3.And( is_pn_valid(pt), old.pages[pt].type == dt.page_type.PAGE_TYPE_X86_PT, old.pages[pt].owner == old.current, # Index is a valid page index z3.ULT(index, 512), is_pn_valid(frame), old.pages[frame].type == dt.page_type.PAGE_TYPE_FRAME, old.pages[frame].owner == old.current, # index must be preset old.pages[pt].data(index) & dt.PTE_P != 0, # the entry in the pt must be the frame z3.Extract(63, 40, z3.UDiv(old.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + frame) == z3.BitVecVal(0, 24), z3.Extract(39, 0, z3.UDiv(old.pages_ptr_to_int, util.i64( dt.PAGE_SIZE)) + frame) == z3.Extract(51, 12, old.pages[pt].data(index)), # no unsafe bits in perm is set perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, # P bit is set in perm perm & dt.PTE_P != 0 ) new = old.copy() new.pages[pt].data[index] = ( (z3.UDiv(new.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + frame) << dt.PTE_PFN_SHIFT) | perm # The only thing that changed is the permission. new.pages[pt].pgtable_perm[index] = perm new.flush_tlb(old.current) return cond, util.If(cond, new, old)
def _sdivC(self, num_expr, den_expr): """Divide (signed) @num by @den (Expr) as C would See modint.__div__ for implementation choice """ num, den = self.from_expr(num_expr), self.from_expr(den_expr) num_s = self.from_expr(num_expr.signExtend(num_expr.size * 2)) den_s = self.from_expr(den_expr.signExtend(den_expr.size * 2)) result_sign = z3.If( num_s * den_s >= 0, z3.BitVecVal(1, num.size()), z3.BitVecVal(-1, num.size()), ) return z3.UDiv(self._abs(num), self._abs(den)) * result_sign
def free_page_table_page(old, frm, index, to, from_type, to_type): cond = z3.And( # The frm pn has the correct type and owned by current is_pn_valid(frm), old.pages[frm].type == from_type, old.pages[frm].owner == old.current, # Index is a valid page index z3.ULT(index, 512), # The to pn has the correct type and owned by current is_pn_valid(to), old.pages[to].type == to_type, old.pages[to].owner == old.current, # index does have the P bit in the from page old.pages[frm].data(index) & dt.PTE_P != 0, # The current pgtable entry matches to... z3.Extract(63, 40, z3.UDiv(old.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + to) == z3.BitVecVal(0, 24), z3.Extract(39, 0, z3.UDiv(old.pages_ptr_to_int, util.i64( dt.PAGE_SIZE)) + to) == z3.Extract(51, 12, old.pages[frm].data(index)), ) new = old.copy() new.pages[frm].data[index] = util.i64(0) new.pages[to].owner = z3.BitVecVal(0, dt.pid_t) new.pages[to].type = dt.page_type.PAGE_TYPE_FREE new.procs[old.current].nr_pages[to] -= 1 new.flush_tlb(old.current) return cond, util.If(cond, new, old)
def initial(self, instance): def trim(var, type): if var.size() == type.size(): return var return z3.Extract(type.size() - 1, 0, var) def extend(var): if var.size() < self.get_types()[-1].size(): v = z3.ZeroExt(self.get_types()[2].size() - var.size(), var) return v return var ref = instance._fields[self._name][0] perm1 = lambda fn, idx: trim(z3.UDiv(idx, 16) + 1 , type=self.get_types()[1][0]) perm2 = lambda fn, idx: trim(z3.URem(idx, 16), type=self.get_types()[1][1]) perm_inv = lambda fn, owned1, owned2: extend(owned1 - 1) * 16 + extend(owned2 % 16) instance._fields[self._name] = (ref, perm1, perm2, perm_inv)
def extintr(old, vector): pid = old.vectors[vector].owner cond = is_pid_valid(pid) cond2 = z3.And(cond, old.procs[pid].state == dt.proc_state.PROC_SLEEPING) vector = z3.ZeroExt(64 - vector.size(), vector) idx = z3.UDiv(vector, 64) mask = 1 << (vector % 64) new = old.copy() new.procs[pid].intr[idx] = new.procs[pid].intr(idx) | mask new2 = new.copy() new2.procs[pid].state = dt.proc_state.PROC_RUNNABLE new2.procs[pid].ipc_from = z3.BitVecVal(0, dt.pid_t) new2.procs[pid].ipc_val = vector new2.procs[pid].ipc_size = z3.BitVecVal(0, dt.size_t) return cond, util.If(cond, util.If(cond2, new2, new), old)
def sys_map_pml4(old, pid, index, perm): cond = z3.And( is_pid_valid(pid), # the pid is either current or an embryo belonging to current z3.Or(pid == old.current, z3.And( old.procs[pid].ppid == old.current, old.procs[pid].state == dt.proc_state.PROC_EMBRYO)), # Index is a valid page index z3.ULT(index, 512), # perm has no unsafe bits on it and it is present and non-writable perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, perm & dt.PTE_P != 0, perm & dt.PTE_W == 0, # index does not have the P bit in the page table root at that index old.pages[old.procs[pid].page_table_root].data( index) & dt.PTE_P == 0, ) new = old.copy() frm = old.procs[pid].page_table_root new.pages[frm].data[index] = ( (z3.UDiv(new.pages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + frm) << dt.PTE_PFN_SHIFT) | perm # maintain the "shadow" pgtable new.pages[frm].pgtable_pn[index] = frm new.pages[frm].pgtable_perm[index] = perm new.pages[frm].pgtable_type[index] = dt.PGTYPE_PAGE new.pages[frm].pgtable_reverse_pn = frm new.pages[frm].pgtable_reverse_idx = index new.flush_tlb(pid) return cond, util.If(cond, new, old)
def from_ExprOp(self, expr): args = map(self.from_expr, expr.args) res = args[0] if len(args) > 1: for arg in args[1:]: if expr.op in self.trivial_ops: res = eval("res %s arg" % expr.op) elif expr.op == ">>": res = z3.LShR(res, arg) elif expr.op == "a>>": res = res >> arg elif expr.op == "a<<": res = res << arg elif expr.op == "<<<": res = z3.RotateLeft(res, arg) elif expr.op == ">>>": res = z3.RotateRight(res, arg) elif expr.op == "idiv": res = res / arg elif expr.op == "udiv": res = z3.UDiv(res, arg) elif expr.op == "imod": res = res % arg elif expr.op == "umod": res = z3.URem(res, arg) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) elif expr.op == 'parity': arg = z3.Extract(7, 0, res) res = z3.BitVecVal(1, 1) for i in xrange(8): res = res ^ z3.Extract(i, i, arg) elif expr.op == '-': res = -res else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) return res
def sys_alloc_port(old, port): cond = z3.And( old.io[port].owner == 0, old.procs[old.current].use_io_bitmap, ) new = old.copy() new.io[port].owner = old.current new.procs[old.current].nr_ports[port] += 1 page = util.If(z3.ULT(port, 0x8000), new.procs[new.current].io_bitmap_a, new.procs[new.current].io_bitmap_b) port = z3.ZeroExt(64 - port.size(), util.If(z3.ULT(port, 0x8000), port, port - 0x8000)) idx = z3.UDiv(port, 64) mask = 1 << (port % 64) new.pages[page].data[idx] = new.pages[page].data(idx) & ~mask return cond, util.If(cond, new, old)
def sys_map_iommu_frame(old, pt, index, to, perm): cond = z3.And( # to is a valid IOMMU_FRAME owned by current is_dmapn_valid(to), old.dmapages[to].type == dt.page_type.PAGE_TYPE_IOMMU_FRAME, old.dmapages[to].owner == old.current, # pt is a valid X86_PT page owned by current is_pn_valid(pt), old.pages[pt].type == dt.page_type.PAGE_TYPE_X86_PT, old.pages[pt].owner == old.current, # Index valid z3.ULT(index, 512), # permissions contain no unsafe bits perm & (dt.MAX_INT64 ^ dt.PTE_PERM_MASK) == 0, perm & dt.PTE_P != 0, # index slot is unused in pt old.pages[pt].data(index) & dt.PTE_P == 0, ) new = old.copy() new.pages[pt].data[index] = ( (z3.UDiv(new.dmapages_ptr_to_int, util.i64(dt.PAGE_SIZE)) + to) << dt.PTE_PFN_SHIFT) | perm new.pages[pt].pgtable_pn[index] = to new.pages[pt].pgtable_perm[index] = perm new.pages[pt].pgtable_type[index] = dt.PGTYPE_IOMMU_FRAME new.flush_tlb(old.current) return cond, util.If(cond, new, old)
b = z3.BitVec('b', 32) ## Compute the average of a and b. The initial computation we provided ## naively adds them and divides by two, but that is not correct. Modify ## these lines to implement your solution for both unsigned (u_avg) and ## signed (s_avg) division. ## ## Watch out for the difference between signed and unsigned integer ## operations. For example, the Z3 expression (x/2) performs signed ## division, meaning it treats the 32-bit value as a signed integer. ## Similarly, (x>>16) shifts x by 16 bits to the right, treating it ## as a signed integer. ## ## Use z3.UDiv(x, y) for unsigned division of x by y. ## Use z3.LShR(x, y) for unsigned (logical) right shift of x by y bits. u_avg = z3.UDiv(a + b, 2) s_avg = (a + b) / 2 ## Do not change the code below. # u_avg = a|b-(z3.LShR(a^b, 1)) failed! # first div each integer,also with remainder,finally plus them u_avg = z3.UDiv(a, 2) + z3.UDiv(b, 2) + (a % 2 + b % 2) / 2 # approach2: from hack's delight u_avg = (a & b) + z3.LShR((a ^ b), 1) #failed! #s_avg = a/2 + b/2 + (((-1)*(a%2) if (a>>31==1) else (a%2))+((-1)*(b%2) if (b>>31==1) else (b%2)))/2 #s_avg = a/2 + b/2 + (a>>31+b>>31)/2 # from hack's delight again
def walk_bv_udiv(self, formula, args, **kwargs): return z3.UDiv(args[0], args[1])
b = z3.BitVec('b', 32) ## Compute the average of a and b. The initial computation we provided ## naively adds them and divides by two, but that is not correct. Modify ## these lines to implement your solution for both unsigned (u_avg) and ## signed (s_avg) division. ## ## Watch out for the difference between signed and unsigned integer ## operations. For example, the Z3 expression (x/2) performs signed ## division, meaning it treats the 32-bit value as a signed integer. ## Similarly, (x>>16) shifts x by 16 bits to the right, treating it ## as a signed integer. ## ## Use z3.UDiv(x, y) for unsigned division of x by y. ## Use z3.LShR(x, y) for unsigned (logical) right shift of x by y bits. u_avg = z3.UDiv(a + b, 2) s_avg = (a + b) / 2 ## Do not change the code below. ## To compute the reference answers, we extend both a and b by one ## more bit (to 33 bits), add them, divide by two, and shrink back ## down to 32 bits. You are not allowed to "cheat" in this way in ## your answer. az33 = z3.ZeroExt(1, a) bz33 = z3.ZeroExt(1, b) real_u_avg = z3.Extract(31, 0, z3.UDiv(az33 + bz33, 2)) as33 = z3.SignExt(1, a) bs33 = z3.SignExt(1, b) real_s_avg = z3.Extract(31, 0, (as33 + bs33) / 2)
b = z3.BitVec('b', 32) ## Compute the average of a and b. The initial computation we provided ## naively adds them and divides by two, but that is not correct. Modify ## these lines to implement your solution for both unsigned (u_avg) and ## signed (s_avg) division. ## ## Watch out for the difference between signed and unsigned integer ## operations. For example, the Z3 expression (x/2) performs signed ## division, meaning it treats the 32-bit value as a signed integer. ## Similarly, (x>>16) shifts x by 16 bits to the right, treating it ## as a signed integer. ## ## Use z3.UDiv(x, y) for unsigned division of x by y. ## Use z3.LShR(x, y) for unsigned (logical) right shift of x by y bits. u_avg = z3.UDiv(a, 2) + z3.UDiv(b, 2) + (a & b & 1) s_avg = (a + b) / 2 ## Do not change the code below. ## To compute the reference answers, we extend both a and b by one ## more bit (to 33 bits), add them, divide by two, and shrink back ## down to 32 bits. You are not allowed to "cheat" in this way in ## your answer. az33 = z3.ZeroExt(1, a) bz33 = z3.ZeroExt(1, b) real_u_avg = z3.Extract(31, 0, z3.UDiv(az33 + bz33, 2)) as33 = z3.SignExt(1, a) bs33 = z3.SignExt(1, b) real_s_avg = z3.Extract(31, 0, (as33 + bs33) / 2)
def _op_div(a, b): return z3.UDiv(a, b)
def bvudiv(self, other): return type(self)(z3.UDiv(self.value, other.value))