aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure20
-rw-r--r--include/qemu/host-utils.h17
-rw-r--r--target-sparc/ldst_helper.c2
-rw-r--r--tcg/ppc/tcg-target.h2
-rw-r--r--tests/Makefile6
-rw-r--r--tests/test-mul64.c70
-rw-r--r--util/host-utils.c96
7 files changed, 145 insertions, 68 deletions
diff --git a/configure b/configure
index 8789324a9b..bf5970f74b 100755
--- a/configure
+++ b/configure
@@ -3150,6 +3150,22 @@ if compile_prog "" "" ; then
cpuid_h=yes
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
@@ -3692,6 +3708,10 @@ if test "$cpuid_h" = "yes" ; then
echo "CONFIG_CPUID_H=y" >> $config_host_mak
fi
+if test "$int128" = "yes" ; then
+ echo "CONFIG_INT128=y" >> $config_host_mak
+fi
+
if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
fi
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index f0dd850e1f..0f688c1c00 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -28,22 +28,21 @@
#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
#include <limits.h>
-#if defined(__x86_64__)
-#define __HAVE_FAST_MULU64__
+#ifdef CONFIG_INT128
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
uint64_t a, uint64_t b)
{
- __asm__ ("mul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
+ __uint128_t r = (__uint128_t)a * b;
+ *plow = r;
+ *phigh = r >> 64;
}
-#define __HAVE_FAST_MULS64__
+
static inline void muls64(uint64_t *plow, uint64_t *phigh,
int64_t a, int64_t b)
{
- __asm__ ("imul %0\n\t"
- : "=d" (*phigh), "=a" (*plow)
- : "a" (a), "0" (b));
+ __int128_t r = (__int128_t)a * b;
+ *plow = r;
+ *phigh = r >> 64;
}
#else
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index cf1bddf2db..7decd66d0b 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -1850,7 +1850,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
oldreg, env->lsu);
#ifdef DEBUG_MMU
- dump_mmu(stdout, fprintf, env1);
+ dump_mmu(stdout, fprintf, env);
#endif
tlb_flush(env, 1);
}
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index ea26769581..0fdad04ee4 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -99,6 +99,6 @@ typedef enum {
#define tcg_qemu_tb_exec(env, tb_ptr) \
((long __attribute__ ((longcall)) \
- (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
+ (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr)
#endif
diff --git a/tests/Makefile b/tests/Makefile
index a2d62b8596..567e36e777 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -54,6 +54,8 @@ check-unit-y += tests/test-xbzrle$(EXESUF)
gcov-files-test-xbzrle-y = xbzrle.c
check-unit-y += tests/test-cutils$(EXESUF)
gcov-files-test-cutils-y += util/cutils.c
+check-unit-y += tests/test-mul64$(EXESUF)
+gcov-files-test-mul64-y = util/host-utils.c
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -82,7 +84,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
- tests/test-x86-cpuid.o
+ tests/test-x86-cpuid.o tests/test-mul64.o
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
@@ -124,6 +126,8 @@ tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y) qapi-types.o qapi-visit.o libqemuutil.a libqemustub.a
tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
+tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
+
tests/rtc-test$(EXESUF): tests/rtc-test.o
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
tests/fdc-test$(EXESUF): tests/fdc-test.o
diff --git a/tests/test-mul64.c b/tests/test-mul64.c
new file mode 100644
index 0000000000..a0a17f7775
--- /dev/null
+++ b/tests/test-mul64.c
@@ -0,0 +1,70 @@
+/*
+ * Test 64x64 -> 128 multiply subroutines
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include <stdint.h>
+#include "qemu/host-utils.h"
+#include "qemu/osdep.h"
+
+
+typedef struct {
+ uint64_t a, b;
+ uint64_t rh, rl;
+} Test;
+
+static const Test test_u_data[] = {
+ { 1, 1, 0, 1 },
+ { 10000, 10000, 0, 100000000 },
+ { 0xffffffffffffffffULL, 2, 1, 0xfffffffffffffffeULL },
+ { 0xffffffffffffffffULL, 0xffffffffffffffffULL,
+ 0xfffffffffffffffeULL, 0x0000000000000001ULL },
+ { 0x1122334455667788ull, 0x8877665544332211ull,
+ 0x092228fb777ae38full, 0x0a3e963337c60008ull },
+};
+
+static const Test test_s_data[] = {
+ { 1, 1, 0, 1 },
+ { 1, -1, -1, -1 },
+ { -10, -10, 0, 100 },
+ { 10000, 10000, 0, 100000000 },
+ { -1, 2, -1, -2 },
+ { 0x1122334455667788ULL, 0x1122334455667788ULL,
+ 0x01258f60bbc2975cULL, 0x1eace4a3c82fb840ULL },
+};
+
+static void test_u(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_u_data); ++i) {
+ uint64_t rl, rh;
+ mulu64(&rl, &rh, test_u_data[i].a, test_u_data[i].b);
+ g_assert_cmpuint(rl, ==, test_u_data[i].rl);
+ g_assert_cmpuint(rh, ==, test_u_data[i].rh);
+ }
+}
+
+static void test_s(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test_s_data); ++i) {
+ uint64_t rl, rh;
+ muls64(&rl, &rh, test_s_data[i].a, test_s_data[i].b);
+ g_assert_cmpuint(rl, ==, test_s_data[i].rl);
+ g_assert_cmpint(rh, ==, test_s_data[i].rh);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/host-utils/mulu64", test_u);
+ g_test_add_func("/host-utils/muls64", test_s);
+ return g_test_run();
+}
diff --git a/util/host-utils.c b/util/host-utils.c
index 5e3915abba..f0784d6335 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -27,79 +27,63 @@
#include <stdint.h>
#include "qemu/host-utils.h"
-//#define DEBUG_MULDIV
-
/* Long integer helpers */
-#if !defined(__x86_64__)
-static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
-{
- *plow += a;
- /* carry test */
- if (*plow < a)
- (*phigh)++;
- *phigh += b;
-}
-
-static void neg128 (uint64_t *plow, uint64_t *phigh)
+#ifndef CONFIG_INT128
+static inline void mul64(uint64_t *plow, uint64_t *phigh,
+ uint64_t a, uint64_t b)
{
- *plow = ~*plow;
- *phigh = ~*phigh;
- add128(plow, phigh, 1, 0);
-}
-
-static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
-{
- uint32_t a0, a1, b0, b1;
- uint64_t v;
-
- a0 = a;
- a1 = a >> 32;
-
- b0 = b;
- b1 = b >> 32;
+ typedef union {
+ uint64_t ll;
+ struct {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint32_t high, low;
+#else
+ uint32_t low, high;
+#endif
+ } l;
+ } LL;
+ LL rl, rm, rn, rh, a0, b0;
+ uint64_t c;
- v = (uint64_t)a0 * (uint64_t)b0;
- *plow = v;
- *phigh = 0;
+ a0.ll = a;
+ b0.ll = b;
- v = (uint64_t)a0 * (uint64_t)b1;
- add128(plow, phigh, v << 32, v >> 32);
+ rl.ll = (uint64_t)a0.l.low * b0.l.low;
+ rm.ll = (uint64_t)a0.l.low * b0.l.high;
+ rn.ll = (uint64_t)a0.l.high * b0.l.low;
+ rh.ll = (uint64_t)a0.l.high * b0.l.high;
- v = (uint64_t)a1 * (uint64_t)b0;
- add128(plow, phigh, v << 32, v >> 32);
+ c = (uint64_t)rl.l.high + rm.l.low + rn.l.low;
+ rl.l.high = c;
+ c >>= 32;
+ c = c + rm.l.high + rn.l.high + rh.l.low;
+ rh.l.low = c;
+ rh.l.high += (uint32_t)(c >> 32);
- v = (uint64_t)a1 * (uint64_t)b1;
- *phigh += v;
+ *plow = rl.ll;
+ *phigh = rh.ll;
}
/* Unsigned 64x64 -> 128 multiplication */
void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
{
mul64(plow, phigh, a, b);
-#if defined(DEBUG_MULDIV)
- printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
- a, b, *phigh, *plow);
-#endif
}
/* Signed 64x64 -> 128 multiplication */
void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
{
- int sa, sb;
+ uint64_t rh;
- sa = (a < 0);
- if (sa)
- a = -a;
- sb = (b < 0);
- if (sb)
- b = -b;
- mul64(plow, phigh, a, b);
- if (sa ^ sb) {
- neg128(plow, phigh);
+ mul64(plow, &rh, a, b);
+
+ /* Adjust for signs. */
+ if (b < 0) {
+ rh -= a;
}
-#if defined(DEBUG_MULDIV)
- printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
- a, b, *phigh, *plow);
-#endif
+ if (a < 0) {
+ rh -= b;
+ }
+ *phigh = rh;
}
-#endif /* !defined(__x86_64__) */
+#endif /* !CONFIG_INT128 */