Commit e494ead52114e9d7baa9f33bca0e5b15b577c16b
1 parent
86f1d3ac
Restore a more maintainable version of the 64bit multiply code.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3439 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
69 additions
and
34 deletions
host-utils.c
1 | 1 | /* |
2 | 2 | * Utility compute operations used by translated code. |
3 | 3 | * |
4 | + * Copyright (c) 2003 Fabrice Bellard | |
4 | 5 | * Copyright (c) 2007 Aurelien Jarno |
5 | 6 | * |
6 | 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
... | ... | @@ -24,54 +25,88 @@ |
24 | 25 | |
25 | 26 | #include "vl.h" |
26 | 27 | |
27 | -/* Signed 64x64 -> 128 multiplication */ | |
28 | +/* Long integer helpers */ | |
29 | +static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
30 | +{ | |
31 | + *plow += a; | |
32 | + /* carry test */ | |
33 | + if (*plow < a) | |
34 | + (*phigh)++; | |
35 | + *phigh += b; | |
36 | +} | |
28 | 37 | |
29 | -void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b) | |
38 | +static void neg128 (uint64_t *plow, uint64_t *phigh) | |
30 | 39 | { |
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; | |
40 | + *plow = ~*plow; | |
41 | + *phigh = ~*phigh; | |
42 | + add128(plow, phigh, 1, 0); | |
43 | +} | |
39 | 44 | |
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); | |
45 | +static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
46 | +{ | |
47 | + uint32_t a0, a1, b0, b1; | |
48 | + uint64_t v; | |
44 | 49 | |
45 | - ph += (int64_t)pm1 >> 32; | |
46 | - ph += (int64_t)pm2 >> 32; | |
47 | - pm1 = (uint64_t)((uint32_t)pm1) + (uint64_t)((uint32_t)pm2) + (pl >> 32); | |
50 | + a0 = a; | |
51 | + a1 = a >> 32; | |
48 | 52 | |
49 | - *phigh = ph + ((int64_t)pm1 >> 32); | |
50 | - *plow = (pm1 << 32) + (uint32_t)pl; | |
51 | -#endif | |
53 | + b0 = b; | |
54 | + b1 = b >> 32; | |
55 | + | |
56 | + v = (uint64_t)a0 * (uint64_t)b0; | |
57 | + *plow = v; | |
58 | + *phigh = 0; | |
59 | + | |
60 | + v = (uint64_t)a0 * (uint64_t)b1; | |
61 | + add128(plow, phigh, v << 32, v >> 32); | |
62 | + | |
63 | + v = (uint64_t)a1 * (uint64_t)b0; | |
64 | + add128(plow, phigh, v << 32, v >> 32); | |
65 | + | |
66 | + v = (uint64_t)a1 * (uint64_t)b1; | |
67 | + *phigh += v; | |
52 | 68 | } |
53 | 69 | |
70 | + | |
54 | 71 | /* Unsigned 64x64 -> 128 multiplication */ |
55 | -void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b) | |
72 | +void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
56 | 73 | { |
57 | 74 | #if defined(__x86_64__) |
58 | 75 | __asm__ ("mul %0\n\t" |
59 | 76 | : "=d" (*phigh), "=a" (*plow) |
60 | - : "a" (a), "0" (b) | |
61 | - ); | |
77 | + : "a" (a), "0" (b)); | |
62 | 78 | #else |
63 | - uint64_t ph, pm1, pm2, pl; | |
64 | - | |
65 | - pl = (uint64_t)((uint32_t)a) * (uint64_t)((uint32_t)b); | |
66 | - pm1 = (a >> 32) * (uint32_t)b; | |
67 | - pm2 = (uint32_t)a * (b >> 32); | |
68 | - ph = (a >> 32) * (b >> 32); | |
79 | + mul64(plow, phigh, a, b); | |
80 | +#endif | |
81 | +#if defined(DEBUG_MULDIV) | |
82 | + printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", | |
83 | + a, b, *phigh, *plow); | |
84 | +#endif | |
85 | +} | |
69 | 86 | |
70 | - ph += pm1 >> 32; | |
71 | - ph += pm2 >> 32; | |
72 | - pm1 = (uint64_t)((uint32_t)pm1) + (uint64_t)((uint32_t)pm2) + (pl >> 32); | |
87 | +/* Signed 64x64 -> 128 multiplication */ | |
88 | +void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) | |
89 | +{ | |
90 | +#if defined(__x86_64__) | |
91 | + __asm__ ("imul %0\n\t" | |
92 | + : "=d" (*phigh), "=a" (*plow) | |
93 | + : "a" (a), "0" (b)); | |
94 | +#else | |
95 | + int sa, sb; | |
73 | 96 | |
74 | - *phigh = ph + (pm1 >> 32); | |
75 | - *plow = (pm1 << 32) + (uint32_t)pl; | |
97 | + sa = (a < 0); | |
98 | + if (sa) | |
99 | + a = -a; | |
100 | + sb = (b < 0); | |
101 | + if (sb) | |
102 | + b = -b; | |
103 | + mul64(plow, phigh, a, b); | |
104 | + if (sa ^ sb) { | |
105 | + neg128(plow, phigh); | |
106 | + } | |
107 | +#endif | |
108 | +#if defined(DEBUG_MULDIV) | |
109 | + printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", | |
110 | + a, b, *phigh, *plow); | |
76 | 111 | #endif |
77 | 112 | } | ... | ... |