Skip to content

Commit

Permalink
qemu/host-utils: Add wrappers for carry builtins
Browse files Browse the repository at this point in the history
These builtins came in clang 3.8, but are not present in gcc through
version 11.  Even in clang the optimization is only ideal on x86_64,
but never worse than the hand-coding that we currently do.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 16, 2021
1 parent cec07c0 commit 1ec8070
Showing 1 changed file with 50 additions and 0 deletions.
50 changes: 50 additions & 0 deletions include/qemu/host-utils.h
Expand Up @@ -26,6 +26,7 @@
#ifndef HOST_UTILS_H
#define HOST_UTILS_H

#include "qemu/compiler.h"
#include "qemu/bswap.h"

#ifdef CONFIG_INT128
Expand Down Expand Up @@ -581,6 +582,55 @@ static inline bool umul64_overflow(uint64_t x, uint64_t y, uint64_t *ret)
#endif
}

/**
* uadd64_carry - addition with carry-in and carry-out
* @x, @y: addends
* @pcarry: in-out carry value
*
* Computes @x + @y + *@pcarry, placing the carry-out back
* into *@pcarry and returning the 64-bit sum.
*/
static inline uint64_t uadd64_carry(uint64_t x, uint64_t y, bool *pcarry)
{
#if __has_builtin(__builtin_addcll)
unsigned long long c = *pcarry;
x = __builtin_addcll(x, y, c, &c);
*pcarry = c & 1;
return x;
#else
bool c = *pcarry;
/* This is clang's internal expansion of __builtin_addc. */
c = uadd64_overflow(x, c, &x);
c |= uadd64_overflow(x, y, &x);
*pcarry = c;
return x;
#endif
}

/**
* usub64_borrow - subtraction with borrow-in and borrow-out
* @x, @y: addends
* @pborrow: in-out borrow value
*
* Computes @x - @y - *@pborrow, placing the borrow-out back
* into *@pborrow and returning the 64-bit sum.
*/
static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow)
{
#if __has_builtin(__builtin_subcll)
unsigned long long b = *pborrow;
x = __builtin_subcll(x, y, b, &b);
*pborrow = b & 1;
return x;
#else
bool b = *pborrow;
b = usub64_overflow(x, b, &x);
b |= usub64_overflow(x, y, &x);
*pborrow = b;
return x;
#endif
}

/* Host type specific sizes of these routines. */

#if ULONG_MAX == UINT32_MAX
Expand Down

0 comments on commit 1ec8070

Please sign in to comment.