xref: /plan9/sys/src/9/port/mul64fract.c (revision 8d37e088715b1ff15cb35965bb2a0295b7504b78)
1ed250ae1SDavid du Colombier #include <u.h>
2ed250ae1SDavid du Colombier 
3*8d37e088SDavid du Colombier /* mul64fract(uvlong*r, uvlong a, uvlong b)
4*8d37e088SDavid du Colombier  *
5*8d37e088SDavid du Colombier  * Multiply two 64 numbers and return the middle 64 bits of the 128 bit result.
6*8d37e088SDavid du Colombier  *
7*8d37e088SDavid du Colombier  * The assumption is that one of the numbers is a
8*8d37e088SDavid du Colombier  * fixed point number with the integer portion in the
9*8d37e088SDavid du Colombier  * high word and the fraction in the low word.
10*8d37e088SDavid du Colombier  *
11*8d37e088SDavid du Colombier  * There should be an assembler version of this routine
12*8d37e088SDavid du Colombier  * for each architecture.  This one is intended to
13*8d37e088SDavid du Colombier  * make ports easier.
14*8d37e088SDavid du Colombier  *
15*8d37e088SDavid du Colombier  *	ignored		r0 = lo(a0*b0)
16*8d37e088SDavid du Colombier  *	lsw of result	r1 = hi(a0*b0) +lo(a0*b1) +lo(a1*b0)
17*8d37e088SDavid du Colombier  *	msw of result	r2 = 		hi(a0*b1) +hi(a1*b0) +lo(a1*b1)
18*8d37e088SDavid du Colombier  *	ignored		r3 = hi(a1*b1)
19*8d37e088SDavid du Colombier  */
20ed250ae1SDavid du Colombier 
21ed250ae1SDavid du Colombier void
mul64fract(uvlong * r,uvlong a,uvlong b)22ed250ae1SDavid du Colombier mul64fract(uvlong *r, uvlong a, uvlong b)
23ed250ae1SDavid du Colombier {
24ed250ae1SDavid du Colombier 	uvlong bh, bl;
25ed250ae1SDavid du Colombier 	uvlong ah, al;
26ed250ae1SDavid du Colombier 	uvlong res;
27ed250ae1SDavid du Colombier 
28ed250ae1SDavid du Colombier 	bl = b & 0xffffffffULL;
29ed250ae1SDavid du Colombier 	bh = b >> 32;
30ed250ae1SDavid du Colombier 	al = a & 0xffffffffULL;
31ed250ae1SDavid du Colombier 	ah = a >> 32;
32ed250ae1SDavid du Colombier 
33ed250ae1SDavid du Colombier 	res = (al*bl)>>32;
34ed250ae1SDavid du Colombier 	res += (al*bh);
35ed250ae1SDavid du Colombier 	res += (ah*bl);
36ed250ae1SDavid du Colombier 	res += (ah*bh)<<32;
37ed250ae1SDavid du Colombier 
38ed250ae1SDavid du Colombier 	*r = res;
39ed250ae1SDavid du Colombier }
40