From: Aurelien Jarno <aurelien@aurel32.net>
To: Paul Brook <paul@codesourcery.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH, MIPS64] dmult & dmultu emulation
Date: Wed, 16 May 2007 02:00:14 +0200 [thread overview]
Message-ID: <20070516000014.GA6169@amd64.aurel32.net> (raw)
In-Reply-To: <200705152207.01210.paul@codesourcery.com>
On Tue, May 15, 2007 at 10:07:00PM +0100, Paul Brook wrote:
> > The patch below fixes the emulation of dmult and dmultu by doing a real
> > 64x64 -> 128 multiplication.
>
> Can we share the implementation between targets please. We already have an
> implementation of mul64 in target-i386/helper.c.
>
> I've no real preference which implementation we use, I just don't want there
> to be several of them.
Ok, please find an updated patch below. The multiplications functions
are in mul64.c and are now shared by the i386 and mips targets.
Bye,
Aurelien
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.169
diff -u -d -p -r1.169 Makefile.target
--- Makefile.target 8 May 2007 21:05:55 -0000 1.169
+++ Makefile.target 15 May 2007 23:37:00 -0000
@@ -365,6 +365,7 @@ endif
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
VL_OBJS+=cutils.o
+VL_OBJS+=mul64.o
VL_OBJS+=block.o block-raw.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
VL_OBJS+=irq.o
Index: exec-all.h
===================================================================
RCS file: /sources/qemu/qemu/exec-all.h,v
retrieving revision 1.54
diff -u -d -p -r1.54 exec-all.h
--- exec-all.h 10 May 2007 00:33:40 -0000 1.54
+++ exec-all.h 15 May 2007 23:37:00 -0000
@@ -78,6 +78,9 @@ void optimize_flags_init(void);
extern FILE *logfile;
extern int loglevel;
+void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
Index: target-i386/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-i386/helper.c,v
retrieving revision 1.80
diff -u -d -p -r1.80 helper.c
--- target-i386/helper.c 18 Apr 2007 11:15:56 -0000 1.80
+++ target-i386/helper.c 15 May 2007 23:37:00 -0000
@@ -3620,50 +3620,6 @@ static void neg128(uint64_t *plow, uint6
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;
-
- v = (uint64_t)a0 * (uint64_t)b0;
- *plow = v;
- *phigh = 0;
-
- v = (uint64_t)a0 * (uint64_t)b1;
- add128(plow, phigh, v << 32, v >> 32);
-
- v = (uint64_t)a1 * (uint64_t)b0;
- add128(plow, phigh, v << 32, v >> 32);
-
- v = (uint64_t)a1 * (uint64_t)b1;
- *phigh += v;
-#ifdef DEBUG_MULDIV
- printf("mul: 0x%016" PRIx64 " * 0x%016" PRIx64 " = 0x%016" PRIx64 "%016" PRIx64 "\n",
- a, b, *phigh, *plow);
-#endif
-}
-
-static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
-{
- int sa, sb;
- 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);
- }
-}
-
/* return TRUE if overflow */
static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
{
@@ -3731,7 +3687,7 @@ void helper_mulq_EAX_T0(void)
{
uint64_t r0, r1;
- mul64(&r0, &r1, EAX, T0);
+ mulu64(&r1, &r0, EAX, T0);
EAX = r0;
EDX = r1;
CC_DST = r0;
@@ -3742,7 +3698,7 @@ void helper_imulq_EAX_T0(void)
{
uint64_t r0, r1;
- imul64(&r0, &r1, EAX, T0);
+ muls64(&r1, &r0, EAX, T0);
EAX = r0;
EDX = r1;
CC_DST = r0;
@@ -3753,7 +3709,7 @@ void helper_imulq_T0_T1(void)
{
uint64_t r0, r1;
- imul64(&r0, &r1, T0, T1);
+ mulu64(&r1, &r0, T0, T1);
T0 = r0;
CC_DST = r0;
CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.26
diff -u -d -p -r1.26 exec.h
--- target-mips/exec.h 13 May 2007 13:49:43 -0000 1.26
+++ target-mips/exec.h 15 May 2007 23:37:00 -0000
@@ -97,8 +97,6 @@ void do_ddiv (void);
#if TARGET_LONG_BITS > HOST_LONG_BITS
void do_ddivu (void);
#endif
-void do_dmult (void);
-void do_dmultu (void);
#endif
void do_mfc0_random(void);
void do_mfc0_count(void);
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.54
diff -u -d -p -r1.54 op.c
--- target-mips/op.c 13 May 2007 19:22:13 -0000 1.54
+++ target-mips/op.c 15 May 2007 23:37:01 -0000
@@ -874,13 +874,13 @@ void op_msubu (void)
#ifdef TARGET_MIPS64
void op_dmult (void)
{
- CALL_FROM_TB0(do_dmult);
+ CALL_FROM_TB4(muls64, &(env->HI), &(env->LO), T0, T1);
RETURN();
}
void op_dmultu (void)
{
- CALL_FROM_TB0(do_dmultu);
+ CALL_FROM_TB4(mulu64, &(env->HI), &(env->LO), T0, T1);
RETURN();
}
#endif
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 23:37:01 -0000
@@ -228,20 +228,6 @@ void do_div (void)
#endif
#ifdef TARGET_MIPS64
-void do_dmult (void)
-{
- env->LO = (int64_t)T0 * (int64_t)T1;
- /* XXX */
- env->HI = (env->LO | (1ULL << 63)) ? ~0ULL : 0ULL;
-}
-
-void do_dmultu (void)
-{
- env->LO = T0 * T1;
- /* XXX */
- env->HI = 0;
-}
-
void do_ddiv (void)
{
if (T1 != 0) {
--- mul64.c 2007-05-05 22:37:06.310788953 +0200
+++ mul64.c 2007-05-16 01:35:26.000000000 +0200
@@ -0,0 +1,77 @@
+/*
+ * 64x64 -> 128 multiplication
+ *
+ * Copyright (c) 2007 Aurelien Jarno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+/* Signed 64x64 -> 128 multiplication */
+
+void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b)
+{
+#if defined(__x86_64__)
+ __asm__ ("imul %0\n\t"
+ : "=d" (*phigh), "=a" (*plow)
+ : "a" (a), "0" (b)
+ );
+#else
+ int64_t ph;
+ uint64_t pm1, pm2, pl;
+
+ pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
+ pm1 = (a >> 32) * (uint32_t)b;
+ pm2 = (uint32_t)a * (b >> 32);
+ ph = (a >> 32) * (b >> 32);
+
+ ph += (int64_t)pm1 >> 32;
+ pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+
+ *phigh = ph + ((int64_t)pm1 >> 32);
+ *plow = (pm1 << 32) + (uint32_t)pl;
+#endif
+}
+
+
+/* Unsigned 64x64 -> 128 multiplication */
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b)
+{
+#if defined(__x86_64__)
+ __asm__ ("mul %0\n\t"
+ : "=d" (*phigh), "=a" (*plow)
+ : "a" (a), "0" (b)
+ );
+#else
+ uint64_t ph, pm1, pm2, pl;
+
+ pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b);
+ pm1 = (a >> 32) * (uint32_t)b;
+ pm2 = (uint32_t)a * (b >> 32);
+ ph = (a >> 32) * (b >> 32);
+
+ ph += pm1 >> 32;
+ pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32);
+
+ *phigh = ph + (pm1 >> 32);
+ *plow = (pm1 << 32) + (uint32_t)pl;
+#endif
+}
+
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
next prev parent reply other threads:[~2007-05-16 0:08 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2007-05-16 1:26 ` C.W. Betts
2007-05-16 1:26 ` C.W. Betts
2007-05-16 8:38 ` Thiemo Seufer
2007-05-16 9:23 ` Aurelien Jarno
2007-05-16 9:20 ` Aurelien Jarno
2007-05-16 12:01 ` Thiemo Seufer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070516000014.GA6169@amd64.aurel32.net \
--to=aurelien@aurel32.net \
--cc=paul@codesourcery.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.