Richard Henderson <[email protected]> writes:
> These builtins came in with gcc 5 and clang 3.8, which are > slightly newer than our supported minimum compiler versions. > > Signed-off-by: Richard Henderson <[email protected]> > --- > include/qemu/host-utils.h | 225 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 225 insertions(+) > > diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h > index f1e52851e0..fd76f0cbd3 100644 > --- a/include/qemu/host-utils.h > +++ b/include/qemu/host-utils.h > @@ -356,6 +356,231 @@ static inline uint64_t revbit64(uint64_t x) > #endif > } > > +/** > + * sadd32_overflow - addition with overflow indication > + * @x, @y: addends > + * @ret: Output for sum > + * > + * Computes *@ret = @x + @y, and returns true if and only if that > + * value has been truncated. > + */ > +static inline bool sadd32_overflow(int32_t x, int32_t y, int32_t *ret) > +{ > +#if __has_builtin(__builtin_add_overflow) || __GNUC__ >= 5 I was wondering if having multiple compiler tests means we should move this test into compiler.h but it doesn't seem we've done it in any other case except libvixl's GCC_VERSION_OR_NEWER helper. > +/** > + * smul64_overflow - multiplication with overflow indication > + * @x, @y: Input multipliers > + * @ret: Output for product > + * > + * Computes *@ret = @x * @y, and returns true if and only if that > + * value has been truncated. > + */ > +static inline bool smul64_overflow(int64_t x, int64_t y, int64_t *ret) > +{ > +#if __has_builtin(__builtin_mul_overflow) || __GNUC__ >= 5 > + return __builtin_mul_overflow(x, y, ret); > +#else > + uint64_t hi, lo; > + muls64(&lo, &hi, x, y); > + *ret = lo; > + return hi != ((int64_t)lo >> 63); > +#endif > +} > + > +/** > + * umul32_overflow - multiplication with overflow indication > + * @x, @y: Input multipliers > + * @ret: Output for product > + * > + * Computes *@ret = @x * @y, and returns true if and only if that > + * value has been truncated. > + */ > +static inline bool umul32_overflow(uint32_t x, uint32_t y, uint32_t *ret) > +{ > +#if __has_builtin(__builtin_mul_overflow) || __GNUC__ >= 5 > + return __builtin_mul_overflow(x, y, ret); > +#else > + uint64_t z = (uint64_t)x * y; > + *ret = z; > + return z > UINT32_MAX; > +#endif > +} > + > +/** > + * smul64_overflow - multiplication with overflow indication c&p error. > + * @x, @y: Input multipliers > + * @ret: Output for product > + * > + * Computes *@ret = @x * @y, and returns true if and only if that > + * value has been truncated. > + */ > +static inline bool umul64_overflow(uint64_t x, uint64_t y, uint64_t *ret) > +{ > +#if __has_builtin(__builtin_mul_overflow) || __GNUC__ >= 5 > + return __builtin_mul_overflow(x, y, ret); > +#else > + uint64_t hi; > + mulu64(ret, &hi, x, y); > + return hi != 0; > +#endif > +} > + > /* Host type specific sizes of these routines. */ > > #if ULONG_MAX == UINT32_MAX Otherwise: Reviewed-by: Alex Bennée <[email protected]> -- Alex Bennée
