@@ -360,6 +360,76 @@ bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, literalt subtract)
360
360
return result;
361
361
}
362
362
363
+ bvt bv_utilst::saturating_add_sub (
364
+ const bvt &op0,
365
+ const bvt &op1,
366
+ bool subtract,
367
+ representationt rep)
368
+ {
369
+ PRECONDITION (op0.size () == op1.size ());
370
+ PRECONDITION (
371
+ rep == representationt::SIGNED || rep == representationt::UNSIGNED);
372
+
373
+ literalt carry_in = const_literal (subtract);
374
+ literalt carry_out;
375
+
376
+ bvt add_sub_result = op0;
377
+ bvt tmp_op1 = subtract ? inverted (op1) : op1;
378
+
379
+ adder (add_sub_result, tmp_op1, carry_in, carry_out);
380
+
381
+ bvt result;
382
+ result.reserve (add_sub_result.size ());
383
+ if (rep == representationt::UNSIGNED)
384
+ {
385
+ // An unsigned overflow has occurred when carry_out is not equal to
386
+ // subtract: addition with a carry-out means an overflow beyond the maximum
387
+ // representable value, subtraction without a carry-out means an underflow
388
+ // below zero. For saturating arithmetic the former implies that all bits
389
+ // should be set to 1, in the latter case all bits should be set to zero.
390
+ for (const auto &literal : add_sub_result)
391
+ {
392
+ result.push_back (
393
+ subtract ? prop.land (literal, carry_out)
394
+ : prop.lor (literal, carry_out));
395
+ }
396
+ }
397
+ else
398
+ {
399
+ // A signed overflow beyond the maximum representable value occurs when
400
+ // adding two positive numbers and the wrap-around result being negative, or
401
+ // when subtracting a negative from a positive number (and, again, the
402
+ // result being negative).
403
+ literalt overflow_to_max_int = prop.land (bvt{
404
+ !sign_bit (op0),
405
+ subtract ? sign_bit (op1) : !sign_bit (op1),
406
+ sign_bit (add_sub_result)});
407
+ // A signed underflow below the minimum representable value occurs when
408
+ // adding two negative numbers and arriving at a positive result, or
409
+ // subtracting a positive from a negative number (and, again, obtaining a
410
+ // positive wrap-around result).
411
+ literalt overflow_to_min_int = prop.land (bvt{
412
+ sign_bit (op0),
413
+ subtract ? !sign_bit (op1) : sign_bit (op1),
414
+ !sign_bit (add_sub_result)});
415
+
416
+ // set all bits except for the sign bit
417
+ PRECONDITION (!add_sub_result.empty ());
418
+ for (std::size_t i = 0 ; i < add_sub_result.size () - 1 ; ++i)
419
+ {
420
+ const auto &literal = add_sub_result[i];
421
+ result.push_back (prop.land (
422
+ prop.lor (overflow_to_max_int, literal), !overflow_to_min_int));
423
+ }
424
+ // finally add the sign bit
425
+ result.push_back (prop.land (
426
+ prop.lor (overflow_to_min_int, add_sub_result.back ()),
427
+ !overflow_to_max_int));
428
+ }
429
+
430
+ return result;
431
+ }
432
+
363
433
literalt bv_utilst::overflow_add (
364
434
const bvt &op0, const bvt &op1, representationt rep)
365
435
{
0 commit comments