xref: /illumos-gate/usr/src/common/util/multi3.c (revision 74e12c43fe52f2c30f36e65a4d0fb0e8dfd7068a)
1 /*
2  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3  * See https://llvm.org/LICENSE.txt for license information.
4  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5  */
6 
7 #include <sys/byteorder.h>
8 
9 #define	CHAR_BIT 8
10 
11 typedef int		di_int __attribute__((mode(DI)));
12 typedef unsigned int	du_int __attribute__((mode(DI)));
13 typedef int		ti_int __attribute__((mode(TI)));
14 
15 typedef union {
16 	ti_int all;
17 	struct {
18 #if _LITTLE_ENDIAN
19 		du_int low;
20 		di_int high;
21 #else
22 		di_int high;
23 		du_int low;
24 #endif /* _LITTLE_ENDIAN */
25 	} s;
26 } twords;
27 
28 /* Returns: a * b */
29 static
30 ti_int
31 __mulddi3(du_int a, du_int b)
32 {
33 	twords r;
34 	const int bits_in_dword_2 = (int)(sizeof (di_int) * CHAR_BIT) / 2;
35 	const du_int lower_mask = (du_int)~0 >> bits_in_dword_2;
36 	r.s.low = (a & lower_mask) * (b & lower_mask);
37 	du_int t = r.s.low >> bits_in_dword_2;
38 	r.s.low &= lower_mask;
39 	t += (a >> bits_in_dword_2) * (b & lower_mask);
40 	r.s.low += (t & lower_mask) << bits_in_dword_2;
41 	r.s.high = t >> bits_in_dword_2;
42 	t = r.s.low >> bits_in_dword_2;
43 	r.s.low &= lower_mask;
44 	t += (b >> bits_in_dword_2) * (a & lower_mask);
45 	r.s.low += (t & lower_mask) << bits_in_dword_2;
46 	r.s.high += t >> bits_in_dword_2;
47 	r.s.high += (a >> bits_in_dword_2) * (b >> bits_in_dword_2);
48 	return (r.all);
49 }
50 
51 /* Returns: a * b */
52 ti_int
53 __multi3(ti_int a, ti_int b)
54 {
55 	twords x;
56 	x.all = a;
57 	twords y;
58 	y.all = b;
59 	twords r;
60 	r.all = __mulddi3(x.s.low, y.s.low);
61 	r.s.high += x.s.high * y.s.low + x.s.low * y.s.high;
62 	return (r.all);
63 }
64