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 Colombiermul64fract(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