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