summaryrefslogtreecommitdiffstats
path: root/include/qemu/int128.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/qemu/int128.h')
-rw-r--r--include/qemu/int128.h44
1 files changed, 36 insertions, 8 deletions
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index 64500385e3..2ac0746426 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -1,9 +1,9 @@
#ifndef INT128_H
#define INT128_H
-#ifdef CONFIG_INT128
#include "qemu/bswap.h"
+#ifdef CONFIG_INT128
typedef __int128_t Int128;
static inline Int128 int128_make64(uint64_t a)
@@ -155,31 +155,48 @@ static inline void int128_subfrom(Int128 *a, Int128 b)
static inline Int128 bswap128(Int128 a)
{
+#if __has_builtin(__builtin_bswap128)
+ return __builtin_bswap128(a);
+#else
return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
+#endif
}
#else /* !CONFIG_INT128 */
typedef struct Int128 Int128;
+/*
+ * We guarantee that the in-memory byte representation of an
+ * Int128 is that of a host-endian-order 128-bit integer
+ * (whether using this struct or the __int128_t version of the type).
+ * Some code using this type relies on this (eg when copying it into
+ * guest memory or a gdb protocol buffer, or by using Int128 in
+ * a union with other integer types).
+ */
struct Int128 {
+#ifdef HOST_WORDS_BIGENDIAN
+ int64_t hi;
+ uint64_t lo;
+#else
uint64_t lo;
int64_t hi;
+#endif
};
static inline Int128 int128_make64(uint64_t a)
{
- return (Int128) { a, 0 };
+ return (Int128) { .lo = a, .hi = 0 };
}
static inline Int128 int128_makes64(int64_t a)
{
- return (Int128) { a, a >> 63 };
+ return (Int128) { .lo = a, .hi = a >> 63 };
}
static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
{
- return (Int128) { lo, hi };
+ return (Int128) { .lo = lo, .hi = hi };
}
static inline uint64_t int128_get64(Int128 a)
@@ -210,22 +227,22 @@ static inline Int128 int128_one(void)
static inline Int128 int128_2_64(void)
{
- return (Int128) { 0, 1 };
+ return int128_make128(0, 1);
}
static inline Int128 int128_exts64(int64_t a)
{
- return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
+ return int128_make128(a, (a < 0) ? -1 : 0);
}
static inline Int128 int128_and(Int128 a, Int128 b)
{
- return (Int128) { a.lo & b.lo, a.hi & b.hi };
+ return int128_make128(a.lo & b.lo, a.hi & b.hi);
}
static inline Int128 int128_or(Int128 a, Int128 b)
{
- return (Int128) { a.lo | b.lo, a.hi | b.hi };
+ return int128_make128(a.lo | b.lo, a.hi | b.hi);
}
static inline Int128 int128_rshift(Int128 a, int n)
@@ -337,5 +354,16 @@ static inline void int128_subfrom(Int128 *a, Int128 b)
*a = int128_sub(*a, b);
}
+static inline Int128 bswap128(Int128 a)
+{
+ return int128_make128(bswap64(a.hi), bswap64(a.lo));
+}
+
#endif /* CONFIG_INT128 */
+
+static inline void bswap128s(Int128 *s)
+{
+ *s = bswap128(*s);
+}
+
#endif /* INT128_H */