[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation
From: |
Aurelien Jarno |
Subject: |
[Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation |
Date: |
Tue, 15 May 2007 22:49:05 +0200 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
Hi,
The patch below fixes the emulation of dmult and dmultu by doing a real
64x64 -> 128 multiplication.
On x86_64, it uses the mul/imul instruction, an equivalent C code (but
much slower) is provided for other architectures.
Cheers,
Aurelien
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.45
diff -u -d -p -r1.45 op_helper.c
--- target-mips/op_helper.c 13 May 2007 19:22:13 -0000 1.45
+++ target-mips/op_helper.c 15 May 2007 20:40:12 -0000
@@ -230,16 +230,49 @@ void do_div (void)
#ifdef TARGET_MIPS64
void do_dmult (void)
{
- env->LO = (int64_t)T0 * (int64_t)T1;
- /* XXX */
- env->HI = (env->LO | (1ULL << 63)) ? ~0ULL : 0ULL;
+#if defined(__x86_64__)
+ __asm__ ("imul %0\n\t"
+ : "=d" (env->HI), "=a" (env->LO)
+ : "a" (T0), "0" (T1)
+ );
+#else
+ int64_t ph;
+ uint64_t pm1, pm2, pl;
+
+ pl = (uint64_t)((uint32_t)T0) * (uint64_t)((uint32_t)T1);
+ pm1 = ((int64_t)T0 >> 32) * (uint32_t)T1;
+ pm2 = (uint32_t)T0 * ((int64_t)T1 >> 32);
+ ph = ((int64_t)T0 >> 32) * ((int64_t)T1 >> 32);
+
+ ph += ((int64_t)pm1) >> 32;
+ pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+
+ env->HI = ph + ((int64_t)pm1) >> 32;
+ env->LO = (pm1 << 32) + (uint32_t)pl;
+#endif
}
void do_dmultu (void)
{
- env->LO = T0 * T1;
- /* XXX */
- env->HI = 0;
+#if defined(__x86_64__)
+ __asm__ ("mul %0\n\t"
+ : "=d" (env->HI), "=a" (env->LO)
+ : "a" (T0), "0" (T1)
+ );
+#else
+ uint64_t ph, pm1, pm2, pl;
+
+ pl = (uint64_t)((uint32_t)T0) * (uint64_t)((uint32_t)T1);
+ pm1 = (T0 >> 32) * (uint32_t)T1;
+ pm2 = (uint32_t)T0 * (T1 >> 32);
+ ph = (T0 >> 32) * (T1 >> 32);
+
+ ph += pm1 >> 32;
+ pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+
+ env->HI = ph + (pm1 >> 32);
+ env->LO = (pm1 << 32) + (uint32_t)pl;
+#endif
}
void do_ddiv (void)
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' address@hidden | address@hidden
`- people.debian.org/~aurel32 | www.aurel32.net
- [Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation,
Aurelien Jarno <=