qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation
@ 2007-05-15 20:49 Aurelien Jarno
  2007-05-15 21:07 ` Paul Brook
  0 siblings, 1 reply; 8+ messages in thread
From: Aurelien Jarno @ 2007-05-15 20:49 UTC (permalink / raw)
  To: qemu-devel

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
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-05-16 12:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-15 20:49 [Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation Aurelien Jarno
2007-05-15 21:07 ` Paul Brook
2007-05-16  0:00   ` Aurelien Jarno
2007-05-16  9:20     ` Aurelien Jarno
2007-05-16 12:01       ` Thiemo Seufer
     [not found]     ` <74FC5FD4-034C-11DC-8C22-0005025B95B5@hotmail.com>
2007-05-16  1:26       ` C.W. Betts
2007-05-16  8:38       ` Thiemo Seufer
2007-05-16  9:23       ` Aurelien Jarno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).