Commit | Line | Data |
---|---|---|
15637ed4 RG |
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 | } |