/*[ c_div64.c LOCAL CHAR SccsID[]="@(#)c_div64.c 1.5 02/09/94"; 64-bit Divide Functions. ------------------------ ]*/ #include #include #include #include #include #include #include #include #include #include #include #include #include /* ===================================================================== EXTERNAL FUNCTIONS START HERE. ===================================================================== */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Do 64bit = 64bit / 32bit Divide (Signed). */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID div64 IFN4( IS32 *, hr, /* High 32 bits of dividend/quotient */ IS32 *, lr, /* Low 32 bits of dividend/quotient */ IS32, divisor, IS32 *, rem /* Remainder */ ) { if ( *hr & BIT31_MASK ) { if ( divisor & BIT31_MASK ) { /* Negative Dividend :: Negative Divisor */ neg64(hr, lr); divisor = -divisor; divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem); *rem = -*rem; } else { /* Negative Dividend :: Positive Divisor */ neg64(hr, lr); divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem); neg64(hr, lr); *rem = -*rem; } } else { if ( divisor & BIT31_MASK ) { /* Positive Dividend :: Negative Divisor */ divisor = -divisor; divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem); neg64(hr, lr); } else { /* Positive Dividend :: Positive Divisor */ divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem); } } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Do 64bit = 64bit / 32bit Divide (Unsigned). */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLOBAL VOID divu64 IFN4( IU32 *, hr, /* High 32 bits of dividend/quotient */ IU32 *, lr, /* Low 32 bits of dividend/quotient */ IU32, divisor, IU32 *, rem /* Remainder */ ) { ISM32 count; IU32 hd; /* High 32 bits of dividend/quotient */ IU32 ld; /* Low 32 bits of dividend/quotient */ IU32 par_div; /* partial dividend */ IU32 carry1; IU32 carry2; IU32 carry3; hd = *hr; /* Get local copies */ ld = *lr; count = 64; /* Initialise */ par_div = 0; while ( count != 0 ) { /* shift left. We have to watch out for carries from ld to hd (carry1) and hd to par_div (carry2) and par_div to 'carry' (carry3). */ carry1 = carry2 = carry3 = 0; if ( ld & BIT31_MASK ) carry1 = 1; if ( hd & BIT31_MASK ) carry2 = 1; if ( par_div & BIT31_MASK ) carry3 = 1; ld = ld << 1; hd = hd << 1 | carry1; par_div = par_div << 1 | carry2; /* check if divisor 'goes into' partial dividend */ if ( carry3 || divisor <= par_div ) { /* Yes it does */ par_div = par_div - divisor; ld = ld | 1; /* output a 1 bit */ } count--; } *rem = par_div; /* Return results */ *hr = hd; *lr = ld; }