literalt bv_utilst::overflow_add( const bvt &op0, const bvt &op1, representationt rep) { if(rep==SIGNED) { // An overflow occurs if the signs of the two operands are the same // and the sign of the sum is the opposite. literalt old_sign=op0[op0.size()-1]; literalt sign_the_same=prop.lequal(op0[op0.size()-1], op1[op1.size()-1]); bvt result=add(op0, op1); return prop.land(sign_the_same, prop.lxor(result[result.size()-1], old_sign)); } else if(rep==UNSIGNED) { // overflow is simply carry-out return carry_out(op0, op1, const_literal(false)); } else assert(false); }
literalt bv_utilst::overflow_sub( const bvt &op0, const bvt &op1, representationt rep) { if(rep==SIGNED) { // We special-case x-INT_MIN, which is >=0 if // x is negative, always representable, and // thus not an overflow. literalt op1_is_int_min=is_int_min(op1); literalt op0_is_negative=op0[op0.size()-1]; return prop.lselect(op1_is_int_min, !op0_is_negative, overflow_add(op0, negate(op1), SIGNED)); } else if(rep==UNSIGNED) { // overflow is simply _negated_ carry-out return !carry_out(op0, inverted(op1), const_literal(true)); } else assert(false); }