aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-11-13 03:22:23 +0000
committerRichard Henderson <richard.henderson@linaro.org>2021-05-16 07:12:26 -0500
commit1ec8070e58a30bd175a1c7186bff797488e8a17b (patch)
tree482cfc1e7087dc6dcd036a09732516e6112a7f55 /include
parentcec07c0b6129757337282287870da2d4c3958f48 (diff)
downloadqemu-1ec8070e58a30bd175a1c7186bff797488e8a17b.zip
qemu-1ec8070e58a30bd175a1c7186bff797488e8a17b.tar.gz
qemu-1ec8070e58a30bd175a1c7186bff797488e8a17b.tar.bz2
qemu/host-utils: Add wrappers for carry builtins
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>
Diffstat (limited to 'include')
-rw-r--r--include/qemu/host-utils.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index cb95626..711b221 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -26,6 +26,7 @@
#ifndef HOST_UTILS_H
#define HOST_UTILS_H
+#include "qemu/compiler.h"
#include "qemu/bswap.h"
#ifdef CONFIG_INT128
@@ -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