xref: /original-bsd/lib/libc/quad/muldi3.c (revision b5ed8b48)
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 short *d;
35   unsigned long acc;
36 
37   m /= sizeof *a;
38   n /= sizeof *b;
39 
40   for (i = m + n, d = c; i-- > 0; *d++ = 0)
41     ;
42 
43   for (j = little_end (n); is_not_msd (j, n); j = next_msd (j))
44     {
45       unsigned short *c1 = c + j + little_end (2);
46       acc = 0;
47       for (i = little_end (m); is_not_msd (i, m); i = next_msd (i))
48 	{
49 	  /* Widen before arithmetic to avoid loss of high bits.  */
50 	  acc += (unsigned long) a[i] * b[j] + c1[i];
51 	  c1[i] = acc & low16;
52 	  acc = acc >> 16;
53 	}
54       c1[i] = acc;
55     }
56 }
57