/******************************************************************************
*									      *
*  64x64 BIT MULTIPLY (UNSIGNED)					      *
*  01/12/07 (dkc)							      *
*									      *
******************************************************************************/
unsigned int carry(unsigned int a, unsigned int b, unsigned int sum);
void mul64_64(unsigned int a0, unsigned int a2, unsigned int m0,
	      unsigned int m2, unsigned int *product) {
unsigned int a1,a3,m1,m3,temp;
unsigned int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15;
unsigned int s0,s1,s2,s3;
unsigned int c1,c2,c3;
a1=a0&0xffff;
a0=a0>>16;
a3=a2&0xffff;
a2=a2>>16;
m1=m0&0xffff;
m0=m0>>16;
m3=m2&0xffff;
m2=m2>>16;

p0=a0*m0;

p1=a0*m1;
p2=a1*m0;

p3=a0*m2;
p4=a1*m1;
p5=a2*m0;

p6=a0*m3;
p7=a1*m2;
p8=a2*m1;
p9=a3*m0;

p10=a1*m3;
p11=a2*m2;
p12=a3*m1;

p13=a2*m3;
p14=a3*m2;

p15=a3*m3;

s3=p15+(p14<<16);
c3=carry(p15,(p14<<16),s3);
temp=s3+(p13<<16);
c3+=carry(s3,(p13<<16),temp);
s3=temp;

s2=p12+(p14>>16);
c2=carry(p12,(p14>>16),s2);
temp=s2+(p13>>16);
c2+=carry(s2,(p13>>16),temp);
s2=temp;
temp=s2+p11;
c2+=carry(s2,p11,temp);
s2=temp;
temp=s2+p10;
c2+=carry(s2,p10,temp);
s2=temp;
temp=s2+(p9<<16);
c2+=carry(s2,(p9<<16),temp);
s2=temp;
temp=s2+(p8<<16);
c2+=carry(s2,(p8<<16),temp);
s2=temp;
temp=s2+(p7<<16);
c2+=carry(s2,(p7<<16),temp);
s2=temp;
temp=s2+(p6<<16);
c2+=carry(s2,(p6<<16),temp);
s2=temp;

s1=p5+(p9>>16);
c1=carry(p5,(p9>16),s1);
temp=s1+(p8>>16);
c1+=carry(s1,(p8>>16),temp);
s1=temp;
temp=s1+(p7>>16);
c1+=carry(s1,(p7>>16),temp);
s1=temp;
temp=s1+(p6>>16);
c1+=carry(s1,(p6>>16),temp);
s1=temp;
temp=s1+p4;
c1+=carry(s1,p4,temp);
s1=temp;
temp=s1+p3;
c1+=carry(s1,p3,temp);
s1=temp;
temp=s1+(p2<<16);
c1+=carry(s1,(p2<<16),temp);
s1=temp;
temp=s1+(p1<<16);
c1+=carry(s1,(p1<<16),temp);
s1=temp;

s0=p0+(p2>>16);
s0=s0+(p1>>16);

temp=s2+c3;
c2+=carry(s2,c3,temp);
s2=temp;

temp=s1+c2;
c1+=carry(s1,c2,temp);
s1=temp;

s0=s0+c1;

*product=s0;
*(product+1)=s1;
*(product+2)=s2;
*(product+3)=s3;
return;
}