host-utils: Use __int128_t for mul[us]64

Replace some x86_64 specific inline assembly with something that
all 64-bit hosts ought to optimize well.  At worst this becomes
a call to the gcc __multi3 routine, which is no worse than our
implementation in util/host-utils.c.

With gcc 4.7, we get identical code generation for x86_64.  We
now get native multiplication on ia64 and s390x hosts.  With minor
improvements to gcc we can get it for ppc64 as well.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
Richard Henderson 2013-02-16 12:46:59 -08:00 committed by Blue Swirl
parent be96bd3fbf
commit f540166b7d
3 changed files with 30 additions and 11 deletions

20
configure vendored
View File

@ -3150,6 +3150,22 @@ if compile_prog "" "" ; then
cpuid_h=yes cpuid_h=yes
fi fi
########################################
# check if __[u]int128_t is usable.
int128=no
cat > $TMPC << EOF
__int128_t a;
__uint128_t b;
int main (void) {
a = a + b;
b = a * b;
return 0;
}
EOF
if compile_prog "" "" ; then
int128=yes
fi
########################################## ##########################################
# End of CC checks # End of CC checks
@ -3692,6 +3708,10 @@ if test "$cpuid_h" = "yes" ; then
echo "CONFIG_CPUID_H=y" >> $config_host_mak echo "CONFIG_CPUID_H=y" >> $config_host_mak
fi fi
if test "$int128" = "yes" ; then
echo "CONFIG_INT128=y" >> $config_host_mak
fi
if test "$glusterfs" = "yes" ; then if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
fi fi

View File

@ -28,22 +28,21 @@
#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */ #include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
#include <limits.h> #include <limits.h>
#if defined(__x86_64__) #ifdef CONFIG_INT128
#define __HAVE_FAST_MULU64__
static inline void mulu64(uint64_t *plow, uint64_t *phigh, static inline void mulu64(uint64_t *plow, uint64_t *phigh,
uint64_t a, uint64_t b) uint64_t a, uint64_t b)
{ {
__asm__ ("mul %0\n\t" __uint128_t r = (__uint128_t)a * b;
: "=d" (*phigh), "=a" (*plow) *plow = r;
: "a" (a), "0" (b)); *phigh = r >> 64;
} }
#define __HAVE_FAST_MULS64__
static inline void muls64(uint64_t *plow, uint64_t *phigh, static inline void muls64(uint64_t *plow, uint64_t *phigh,
int64_t a, int64_t b) int64_t a, int64_t b)
{ {
__asm__ ("imul %0\n\t" __int128_t r = (__int128_t)a * b;
: "=d" (*phigh), "=a" (*plow) *plow = r;
: "a" (a), "0" (b)); *phigh = r >> 64;
} }
#else #else
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);

View File

@ -30,7 +30,7 @@
//#define DEBUG_MULDIV //#define DEBUG_MULDIV
/* Long integer helpers */ /* Long integer helpers */
#if !defined(__x86_64__) #ifndef CONFIG_INT128
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{ {
*plow += a; *plow += a;
@ -102,4 +102,4 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
a, b, *phigh, *plow); a, b, *phigh, *plow);
#endif #endif
} }
#endif /* !defined(__x86_64__) */ #endif /* !CONFIG_INT128 */