/* new double-float divide routine, by jrd */ #include "flonum.h" #ifdef L_divdf3 double __divdf3(num, denom) double num, denom; { double local_num = num; double local_denom = denom; struct bitdouble * num_bdp = (struct bitdouble *)(&local_num); struct bitdouble * den_bdp = (struct bitdouble *)(&local_denom); short num_exp = num_bdp->exp, den_exp = den_bdp->exp; short result_sign = 0; /* register */ unsigned long num_m1, num_m2, num_m3, num_m4; register unsigned long den_m1, den_m2, den_m3, den_m4; unsigned long result_mant[3]; unsigned long result_mask; short result_idx; if ((num_exp == 0) || (den_exp == 0)) /* zzz should really cause trap */ return(0.0); /* deal with signs */ result_sign = result_sign + num_bdp->sign - den_bdp->sign; /* unpack the numbers */ num_m1 = num_bdp->mant1 | 0x00100000; /* hidden bit */ num_m2 = num_bdp->mant2; num_m4 = num_m3 = 0; den_m1 = den_bdp->mant1 | 0x00100000; /* hidden bit */ den_m2 = den_bdp->mant2; den_m4 = den_m3 = 0; #if 0 /* buy a little extra accuracy by shifting num and denum up 10 bits */ for (result_idx /* loop counter */ = 0 ; result_idx < 10 ; result_idx++) { ASL3(num_m1, num_m2, num_m3); ASL3(den_m1, den_m2, den_m3); } #endif /* hot wire result mask and index */ result_mask = 0x00100000; /* start at top mantissa bit */ result_idx = 0; /* of first word */ result_mant[0] = 0; result_mant[1] = 0; result_mant[2] = 0; /* if denom is greater than num here, shift denom right one and dec num expt */ if (den_m1 < num_m1) goto kludge1; /* C is assembly language, remember? */ if (den_m1 > num_m1) goto kludge0; if (den_m2 <= num_m2) /* first word eq, try 2nd */ goto kludge1; kludge0: num_exp--; ASR4(den_m1, den_m2, den_m3, den_m4); kludge1: for ( ; !((result_idx == 2) && (result_mask & 0x40000000)) ; ) { /* if num >= den, subtract den from num and set bit in result */ if (num_m1 > den_m1) goto kludge2; if (num_m1 < den_m1) goto kludge3; if (num_m2 > den_m2) goto kludge2; if (num_m2 < den_m2) goto kludge3; if (num_m3 > den_m3) goto kludge2; if (num_m3 < den_m3) goto kludge3; if (num_m4 < den_m4) goto kludge3; kludge2: result_mant[result_idx] |= result_mask; SUB4(den_m1, den_m2, den_m3, den_m4, num_m1, num_m2, num_m3, num_m4); kludge3: ASR4(den_m1, den_m2, den_m3, den_m4); result_mask >>= 1; if (result_mask == 0) /* next word? */ { result_mask = 0x80000000; result_idx++; } } /* stick in last half-bit if necessary */ if (result_mant[2]) { den_m1 = 0; /* handy register */ den_m2 = 1; /* busted ADD2(den_m1, den_m2, result_mant[0], result_mant[1]); */ result_mant[1]++; if (result_mant[1] == 0) result_mant[0]++; if (result_mant[0] & 0x00200000) /* overflow? */ { num_exp--; } } /* compute the resultant exponent */ num_exp = num_exp - den_exp + 0x3FF; /* reconstruct the result in local_num */ num_bdp->sign = result_sign; num_bdp->exp = num_exp; num_bdp->mant1 = result_mant[0] & 0xFFFFF; num_bdp->mant2 = result_mant[1]; /* done! */ return(local_num); } #endif