Commit 69d357286d0ab5a852e827dad1dc4b05917aaaa8
1 parent
100ce988
More generic 64 bit multiplication support, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2821 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
84 additions
and
65 deletions
Makefile.target
... | ... | @@ -365,6 +365,7 @@ endif |
365 | 365 | # must use static linking to avoid leaving stuff in virtual address space |
366 | 366 | VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o |
367 | 367 | VL_OBJS+=cutils.o |
368 | +VL_OBJS+=host-utils.o | |
368 | 369 | VL_OBJS+=block.o block-raw.o |
369 | 370 | 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 |
370 | 371 | VL_OBJS+=irq.o | ... | ... |
exec-all.h
... | ... | @@ -78,6 +78,9 @@ void optimize_flags_init(void); |
78 | 78 | extern FILE *logfile; |
79 | 79 | extern int loglevel; |
80 | 80 | |
81 | +void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b); | |
82 | +void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); | |
83 | + | |
81 | 84 | int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); |
82 | 85 | int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); |
83 | 86 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); | ... | ... |
host-utils.c
0 → 100644
1 | +/* | |
2 | + * Utility compute operations used by translated code. | |
3 | + * | |
4 | + * Copyright (c) 2007 Aurelien Jarno | |
5 | + * | |
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | + * of this software and associated documentation files (the "Software"), to deal | |
8 | + * in the Software without restriction, including without limitation the rights | |
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | + * copies of the Software, and to permit persons to whom the Software is | |
11 | + * furnished to do so, subject to the following conditions: | |
12 | + * | |
13 | + * The above copyright notice and this permission notice shall be included in | |
14 | + * all copies or substantial portions of the Software. | |
15 | + * | |
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | + * THE SOFTWARE. | |
23 | + */ | |
24 | + | |
25 | +#include "vl.h" | |
26 | + | |
27 | +/* Signed 64x64 -> 128 multiplication */ | |
28 | + | |
29 | +void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b) | |
30 | +{ | |
31 | +#if defined(__x86_64__) | |
32 | + __asm__ ("imul %0\n\t" | |
33 | + : "=d" (*phigh), "=a" (*plow) | |
34 | + : "a" (a), "0" (b) | |
35 | + ); | |
36 | +#else | |
37 | + int64_t ph; | |
38 | + uint64_t pm1, pm2, pl; | |
39 | + | |
40 | + pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b); | |
41 | + pm1 = (a >> 32) * (uint32_t)b; | |
42 | + pm2 = (uint32_t)a * (b >> 32); | |
43 | + ph = (a >> 32) * (b >> 32); | |
44 | + | |
45 | + ph += (int64_t)pm1 >> 32; | |
46 | + pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32); | |
47 | + | |
48 | + *phigh = ph + ((int64_t)pm1 >> 32); | |
49 | + *plow = (pm1 << 32) + (uint32_t)pl; | |
50 | +#endif | |
51 | +} | |
52 | + | |
53 | +/* Unsigned 64x64 -> 128 multiplication */ | |
54 | +void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b) | |
55 | +{ | |
56 | +#if defined(__x86_64__) | |
57 | + __asm__ ("mul %0\n\t" | |
58 | + : "=d" (*phigh), "=a" (*plow) | |
59 | + : "a" (a), "0" (b) | |
60 | + ); | |
61 | +#else | |
62 | + uint64_t ph, pm1, pm2, pl; | |
63 | + | |
64 | + pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b); | |
65 | + pm1 = (a >> 32) * (uint32_t)b; | |
66 | + pm2 = (uint32_t)a * (b >> 32); | |
67 | + ph = (a >> 32) * (b >> 32); | |
68 | + | |
69 | + ph += pm1 >> 32; | |
70 | + pm1 = (uint64_t)((uint32_t)pm1) + pm2 + (pl >> 32); | |
71 | + | |
72 | + *phigh = ph + (pm1 >> 32); | |
73 | + *plow = (pm1 << 32) + (uint32_t)pl; | |
74 | +#endif | |
75 | +} | ... | ... |
target-i386/helper.c
... | ... | @@ -3620,50 +3620,6 @@ static void neg128(uint64_t *plow, uint64_t *phigh) |
3620 | 3620 | add128(plow, phigh, 1, 0); |
3621 | 3621 | } |
3622 | 3622 | |
3623 | -static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
3624 | -{ | |
3625 | - uint32_t a0, a1, b0, b1; | |
3626 | - uint64_t v; | |
3627 | - | |
3628 | - a0 = a; | |
3629 | - a1 = a >> 32; | |
3630 | - | |
3631 | - b0 = b; | |
3632 | - b1 = b >> 32; | |
3633 | - | |
3634 | - v = (uint64_t)a0 * (uint64_t)b0; | |
3635 | - *plow = v; | |
3636 | - *phigh = 0; | |
3637 | - | |
3638 | - v = (uint64_t)a0 * (uint64_t)b1; | |
3639 | - add128(plow, phigh, v << 32, v >> 32); | |
3640 | - | |
3641 | - v = (uint64_t)a1 * (uint64_t)b0; | |
3642 | - add128(plow, phigh, v << 32, v >> 32); | |
3643 | - | |
3644 | - v = (uint64_t)a1 * (uint64_t)b1; | |
3645 | - *phigh += v; | |
3646 | -#ifdef DEBUG_MULDIV | |
3647 | - printf("mul: 0x%016" PRIx64 " * 0x%016" PRIx64 " = 0x%016" PRIx64 "%016" PRIx64 "\n", | |
3648 | - a, b, *phigh, *plow); | |
3649 | -#endif | |
3650 | -} | |
3651 | - | |
3652 | -static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) | |
3653 | -{ | |
3654 | - int sa, sb; | |
3655 | - sa = (a < 0); | |
3656 | - if (sa) | |
3657 | - a = -a; | |
3658 | - sb = (b < 0); | |
3659 | - if (sb) | |
3660 | - b = -b; | |
3661 | - mul64(plow, phigh, a, b); | |
3662 | - if (sa ^ sb) { | |
3663 | - neg128(plow, phigh); | |
3664 | - } | |
3665 | -} | |
3666 | - | |
3667 | 3623 | /* return TRUE if overflow */ |
3668 | 3624 | static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b) |
3669 | 3625 | { |
... | ... | @@ -3731,7 +3687,7 @@ void helper_mulq_EAX_T0(void) |
3731 | 3687 | { |
3732 | 3688 | uint64_t r0, r1; |
3733 | 3689 | |
3734 | - mul64(&r0, &r1, EAX, T0); | |
3690 | + mulu64(&r1, &r0, EAX, T0); | |
3735 | 3691 | EAX = r0; |
3736 | 3692 | EDX = r1; |
3737 | 3693 | CC_DST = r0; |
... | ... | @@ -3742,7 +3698,7 @@ void helper_imulq_EAX_T0(void) |
3742 | 3698 | { |
3743 | 3699 | uint64_t r0, r1; |
3744 | 3700 | |
3745 | - imul64(&r0, &r1, EAX, T0); | |
3701 | + muls64(&r1, &r0, EAX, T0); | |
3746 | 3702 | EAX = r0; |
3747 | 3703 | EDX = r1; |
3748 | 3704 | CC_DST = r0; |
... | ... | @@ -3753,7 +3709,7 @@ void helper_imulq_T0_T1(void) |
3753 | 3709 | { |
3754 | 3710 | uint64_t r0, r1; |
3755 | 3711 | |
3756 | - imul64(&r0, &r1, T0, T1); | |
3712 | + muls64(&r1, &r0, T0, T1); | |
3757 | 3713 | T0 = r0; |
3758 | 3714 | CC_DST = r0; |
3759 | 3715 | CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); | ... | ... |
target-mips/exec.h
target-mips/op.c
... | ... | @@ -874,13 +874,13 @@ void op_msubu (void) |
874 | 874 | #ifdef TARGET_MIPS64 |
875 | 875 | void op_dmult (void) |
876 | 876 | { |
877 | - CALL_FROM_TB0(do_dmult); | |
877 | + CALL_FROM_TB4(muls64, &(env->HI), &(env->LO), T0, T1); | |
878 | 878 | RETURN(); |
879 | 879 | } |
880 | 880 | |
881 | 881 | void op_dmultu (void) |
882 | 882 | { |
883 | - CALL_FROM_TB0(do_dmultu); | |
883 | + CALL_FROM_TB4(mulu64, &(env->HI), &(env->LO), T0, T1); | |
884 | 884 | RETURN(); |
885 | 885 | } |
886 | 886 | #endif | ... | ... |
target-mips/op_helper.c
... | ... | @@ -228,20 +228,6 @@ void do_div (void) |
228 | 228 | #endif |
229 | 229 | |
230 | 230 | #ifdef TARGET_MIPS64 |
231 | -void do_dmult (void) | |
232 | -{ | |
233 | - env->LO = (int64_t)T0 * (int64_t)T1; | |
234 | - /* XXX */ | |
235 | - env->HI = (env->LO | (1ULL << 63)) ? ~0ULL : 0ULL; | |
236 | -} | |
237 | - | |
238 | -void do_dmultu (void) | |
239 | -{ | |
240 | - env->LO = T0 * T1; | |
241 | - /* XXX */ | |
242 | - env->HI = 0; | |
243 | -} | |
244 | - | |
245 | 231 | void do_ddiv (void) |
246 | 232 | { |
247 | 233 | if (T1 != 0) { | ... | ... |