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