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