@samitouri / QOSamiQemu / commits / 1649553313

host-utils: Introduce signed saturation primitives

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Richard Henderson committed Apr 29, 2026 at 04:32 UTC 16495533131af2eb94019e32c72688ea5e1b2742
2 files changed +64 -16
accel/tcg/tcg-runtime-gvec.c
+4 -16
@@ -1109,10 +1109,7 @@ void HELPER(gvec_ssadd32)(void *d, void *a, void *b, uint32_t desc)
1109 for (i = 0; i < oprsz; i += sizeof(int32_t)) {
1110 int32_t ai = *(int32_t *)(a + i);
1111 int32_t bi = *(int32_t *)(b + i);
1112 - int32_t di;
1113 - if (sadd32_overflow(ai, bi, &di)) {
1114 - di = (di < 0 ? INT32_MAX : INT32_MIN);
1115 - }
1112 + int32_t di = sadd32_saturate(ai, bi);
1113 *(int32_t *)(d + i) = di;
1114 }
1115 clear_high(d, oprsz, desc);
@@ -1126,10 +1123,7 @@ void HELPER(gvec_ssadd64)(void *d, void *a, void *b, uint32_t desc)
1123 for (i = 0; i < oprsz; i += sizeof(int64_t)) {
1124 int64_t ai = *(int64_t *)(a + i);
1125 int64_t bi = *(int64_t *)(b + i);
1129 - int64_t di;
1130 - if (sadd64_overflow(ai, bi, &di)) {
1131 - di = (di < 0 ? INT64_MAX : INT64_MIN);
1132 - }
1126 + int64_t di = sadd64_saturate(ai, bi);
1127 *(int64_t *)(d + i) = di;
1128 }
1129 clear_high(d, oprsz, desc);
@@ -1177,10 +1171,7 @@ void HELPER(gvec_sssub32)(void *d, void *a, void *b, uint32_t desc)
1171 for (i = 0; i < oprsz; i += sizeof(int32_t)) {
1172 int32_t ai = *(int32_t *)(a + i);
1173 int32_t bi = *(int32_t *)(b + i);
1180 - int32_t di;
1181 - if (ssub32_overflow(ai, bi, &di)) {
1182 - di = (di < 0 ? INT32_MAX : INT32_MIN);
1183 - }
1174 + int32_t di = ssub32_saturate(ai, bi);
1175 *(int32_t *)(d + i) = di;
1176 }
1177 clear_high(d, oprsz, desc);
@@ -1194,10 +1185,7 @@ void HELPER(gvec_sssub64)(void *d, void *a, void *b, uint32_t desc)
1185 for (i = 0; i < oprsz; i += sizeof(int64_t)) {
1186 int64_t ai = *(int64_t *)(a + i);
1187 int64_t bi = *(int64_t *)(b + i);
1197 - int64_t di;
1198 - if (ssub64_overflow(ai, bi, &di)) {
1199 - di = (di < 0 ? INT64_MAX : INT64_MIN);
1200 - }
1188 + int64_t di = ssub64_saturate(ai, bi);
1189 *(int64_t *)(d + i) = di;
1190 }
1191 clear_high(d, oprsz, desc);
include/qemu/host-utils.h
+60
@@ -606,6 +606,66 @@ static inline bool umul64_overflow(uint64_t x, uint64_t y, uint64_t *ret)
606 return __builtin_mul_overflow(x, y, ret);
607 }
608
609 +/**
610 + * sadd32_saturate - addition with saturation
611 + * @x, @y: addends
612 + *
613 + * Computes @x + @y, and saturates rathern than truncating the result.
614 + */
615 +static inline int32_t sadd32_saturate(int32_t x, int32_t y)
616 +{
617 + int32_t ret;
618 + if (sadd32_overflow(x, y, &ret)) {
619 + ret = y < 0 ? INT32_MIN : INT32_MAX;
620 + }
621 + return ret;
622 +}
623 +
624 +/**
625 + * sadd64_saturate - addition with saturation
626 + * @x, @y: addends
627 + *
628 + * Computes @x + @y, and saturates rathern than truncating the result.
629 + */
630 +static inline int64_t sadd64_saturate(int64_t x, int64_t y)
631 +{
632 + int64_t ret;
633 + if (sadd64_overflow(x, y, &ret)) {
634 + ret = y < 0 ? INT64_MIN : INT64_MAX;
635 + }
636 + return ret;
637 +}
638 +
639 +/**
640 + * ssub32_saturate - subtraction with saturation
641 + * @x, @y: addends
642 + *
643 + * Computes @x + @y, and saturates rathern than truncating the result.
644 + */
645 +static inline bool ssub32_saturate(int32_t x, int32_t y)
646 +{
647 + int32_t ret;
648 + if (ssub32_overflow(x, y, &ret)) {
649 + ret = x < 0 ? INT32_MAX : INT32_MIN;
650 + }
651 + return ret;
652 +}
653 +
654 +/**
655 + * ssub64_saturate - subtraction with saturation
656 + * @x, @y: addends
657 + *
658 + * Computes @x + @y, and saturates rathern than truncating the result.
659 + */
660 +static inline bool ssub64_saturate(int64_t x, int64_t y)
661 +{
662 + int64_t ret;
663 + if (ssub64_overflow(x, y, &ret)) {
664 + ret = x < 0 ? INT64_MAX : INT64_MIN;
665 + }
666 + return ret;
667 +}
668 +
669 /*
670 * Unsigned 128x64 multiplication.
671 * Returns true if the result got truncated to 128 bits.