| 1 | #include "longlong.h" |
| 2 | |
| 3 | static void bmul (); |
| 4 | |
| 5 | long long |
| 6 | __muldi3 (u, v) |
| 7 | long long u, v; |
| 8 | { |
| 9 | long a[2], b[2], c[2][2]; |
| 10 | long_long w; |
| 11 | long_long uu, vv; |
| 12 | |
| 13 | uu.ll = u; |
| 14 | vv.ll = v; |
| 15 | |
| 16 | a[HIGH] = uu.s.high; |
| 17 | a[LOW] = uu.s.low; |
| 18 | b[HIGH] = vv.s.high; |
| 19 | b[LOW] = vv.s.low; |
| 20 | |
| 21 | bmul (a, b, c, sizeof a, sizeof b); |
| 22 | |
| 23 | w.s.high = c[LOW][HIGH]; |
| 24 | w.s.low = c[LOW][LOW]; |
| 25 | return w.ll; |
| 26 | } |
| 27 | |
| 28 | static void |
| 29 | bmul (a, b, c, m, n) |
| 30 | unsigned short *a, *b, *c; |
| 31 | size_t m, n; |
| 32 | { |
| 33 | int i, j; |
| 34 | unsigned long acc; |
| 35 | |
| 36 | bzero (c, m + n); |
| 37 | |
| 38 | m /= sizeof *a; |
| 39 | n /= sizeof *b; |
| 40 | |
| 41 | for (j = little_end (n); is_not_msd (j, n); j = next_msd (j)) |
| 42 | { |
| 43 | unsigned short *c1 = c + j + little_end (2); |
| 44 | acc = 0; |
| 45 | for (i = little_end (m); is_not_msd (i, m); i = next_msd (i)) |
| 46 | { |
| 47 | /* Widen before arithmetic to avoid loss of high bits. */ |
| 48 | acc += (unsigned long) a[i] * b[j] + c1[i]; |
| 49 | c1[i] = acc & low16; |
| 50 | acc = acc >> 16; |
| 51 | } |
| 52 | c1[i] = acc; |
| 53 | } |
| 54 | } |