Commit e494ead52114e9d7baa9f33bca0e5b15b577c16b

Authored by ths
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 * Utility compute operations used by translated code. 2 * Utility compute operations used by translated code.
3 * 3 *
  4 + * Copyright (c) 2003 Fabrice Bellard
4 * Copyright (c) 2007 Aurelien Jarno 5 * Copyright (c) 2007 Aurelien Jarno
5 * 6 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,54 +25,88 @@ @@ -24,54 +25,88 @@
24 25
25 #include "vl.h" 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 /* Unsigned 64x64 -> 128 multiplication */ 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 #if defined(__x86_64__) 74 #if defined(__x86_64__)
58 __asm__ ("mul %0\n\t" 75 __asm__ ("mul %0\n\t"
59 : "=d" (*phigh), "=a" (*plow) 76 : "=d" (*phigh), "=a" (*plow)
60 - : "a" (a), "0" (b)  
61 - ); 77 + : "a" (a), "0" (b));
62 #else 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 #endif 111 #endif
77 } 112 }