diff options
Diffstat (limited to 'include/qemu/int128.h')
-rw-r--r-- | include/qemu/int128.h | 44 |
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 */ |