summaryrefslogtreecommitdiffstats
path: root/qemu/include/qemu/host-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/include/qemu/host-utils.h')
-rw-r--r--qemu/include/qemu/host-utils.h140
1 files changed, 138 insertions, 2 deletions
diff --git a/qemu/include/qemu/host-utils.h b/qemu/include/qemu/host-utils.h
index d4f21c947..1cdae0d0e 100644
--- a/qemu/include/qemu/host-utils.h
+++ b/qemu/include/qemu/host-utils.h
@@ -25,8 +25,7 @@
#ifndef HOST_UTILS_H
#define HOST_UTILS_H 1
-#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
-#include <limits.h>
+#include "qemu/bswap.h"
#ifdef CONFIG_INT128
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
@@ -45,6 +44,12 @@ static inline void muls64(uint64_t *plow, uint64_t *phigh,
*phigh = r >> 64;
}
+/* compute with 96 bit intermediate result: (a*b)/c */
+static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ return (__int128_t)a * b / c;
+}
+
static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
{
if (divisor == 0) {
@@ -75,6 +80,29 @@ void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
int divs128(int64_t *plow, int64_t *phigh, int64_t divisor);
+
+static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ union {
+ uint64_t ll;
+ struct {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint32_t high, low;
+#else
+ uint32_t low, high;
+#endif
+ } l;
+ } u, res;
+ uint64_t rl, rh;
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+}
#endif
/**
@@ -361,6 +389,80 @@ static inline int ctpop64(uint64_t val)
#endif
}
+/**
+ * revbit8 - reverse the bits in an 8-bit value.
+ * @x: The value to modify.
+ */
+static inline uint8_t revbit8(uint8_t x)
+{
+ /* Assign the correct nibble position. */
+ x = ((x & 0xf0) >> 4)
+ | ((x & 0x0f) << 4);
+ /* Assign the correct bit position. */
+ x = ((x & 0x88) >> 3)
+ | ((x & 0x44) >> 1)
+ | ((x & 0x22) << 1)
+ | ((x & 0x11) << 3);
+ return x;
+}
+
+/**
+ * revbit16 - reverse the bits in a 16-bit value.
+ * @x: The value to modify.
+ */
+static inline uint16_t revbit16(uint16_t x)
+{
+ /* Assign the correct byte position. */
+ x = bswap16(x);
+ /* Assign the correct nibble position. */
+ x = ((x & 0xf0f0) >> 4)
+ | ((x & 0x0f0f) << 4);
+ /* Assign the correct bit position. */
+ x = ((x & 0x8888) >> 3)
+ | ((x & 0x4444) >> 1)
+ | ((x & 0x2222) << 1)
+ | ((x & 0x1111) << 3);
+ return x;
+}
+
+/**
+ * revbit32 - reverse the bits in a 32-bit value.
+ * @x: The value to modify.
+ */
+static inline uint32_t revbit32(uint32_t x)
+{
+ /* Assign the correct byte position. */
+ x = bswap32(x);
+ /* Assign the correct nibble position. */
+ x = ((x & 0xf0f0f0f0u) >> 4)
+ | ((x & 0x0f0f0f0fu) << 4);
+ /* Assign the correct bit position. */
+ x = ((x & 0x88888888u) >> 3)
+ | ((x & 0x44444444u) >> 1)
+ | ((x & 0x22222222u) << 1)
+ | ((x & 0x11111111u) << 3);
+ return x;
+}
+
+/**
+ * revbit64 - reverse the bits in a 64-bit value.
+ * @x: The value to modify.
+ */
+static inline uint64_t revbit64(uint64_t x)
+{
+ /* Assign the correct byte position. */
+ x = bswap64(x);
+ /* Assign the correct nibble position. */
+ x = ((x & 0xf0f0f0f0f0f0f0f0ull) >> 4)
+ | ((x & 0x0f0f0f0f0f0f0f0full) << 4);
+ /* Assign the correct bit position. */
+ x = ((x & 0x8888888888888888ull) >> 3)
+ | ((x & 0x4444444444444444ull) >> 1)
+ | ((x & 0x2222222222222222ull) << 1)
+ | ((x & 0x1111111111111111ull) << 3);
+ return x;
+}
+
/* Host type specific sizes of these routines. */
#if ULONG_MAX == UINT32_MAX
@@ -369,14 +471,48 @@ static inline int ctpop64(uint64_t val)
# define clol clo32
# define ctol cto32
# define ctpopl ctpop32
+# define revbitl revbit32
#elif ULONG_MAX == UINT64_MAX
# define clzl clz64
# define ctzl ctz64
# define clol clo64
# define ctol cto64
# define ctpopl ctpop64
+# define revbitl revbit64
#else
# error Unknown sizeof long
#endif
+static inline bool is_power_of_2(uint64_t value)
+{
+ if (!value) {
+ return 0;
+ }
+
+ return !(value & (value - 1));
+}
+
+/* round down to the nearest power of 2*/
+static inline int64_t pow2floor(int64_t value)
+{
+ if (!is_power_of_2(value)) {
+ value = 0x8000000000000000ULL >> clz64(value);
+ }
+ return value;
+}
+
+/* round up to the nearest power of 2 (0 if overflow) */
+static inline uint64_t pow2ceil(uint64_t value)
+{
+ uint8_t nlz = clz64(value);
+
+ if (is_power_of_2(value)) {
+ return value;
+ }
+ if (!nlz) {
+ return 0;
+ }
+ return 1ULL << (64 - nlz);
+}
+
#endif