int ar_ifdiv32 (AR_IEEE_32 *x, const AR_IEEE_32 *a, const AR_IEEE_32 *b, int roundmode) { int i, s; int res = AR_STAT_OK; unsigned long x_lbits, y_lbits, z_lbits, rbits, carry; signed int x_expo; AR_IEEE_32 y, y2, z, z2; /* If either a or b is a NaN, it's the result. */ if (IS_IEEE32_NaN(a)) { *x = *a; return res | AR_STAT_UNDEFINED; } if (IS_IEEE32_NaN(b)) { *x = *b; return res | AR_STAT_UNDEFINED; } s = a->sign ^ b->sign; /* Test for infinities and zeros */ if (b->expo > AR_IEEE32_MAX_EXPO) if (a->expo > AR_IEEE32_MAX_EXPO) { /* infinity / infinity = quiet NaN */ QNaNIEEE32 (x); return res | AR_STAT_UNDEFINED; } else { /* anything / infinity = zero */ if (s) res |= AR_STAT_NEGATIVE; ZEROIEEE32 (*x); x->sign = s; return res | AR_STAT_UNDERFLOW | AR_STAT_ZERO; } if (a->expo > AR_IEEE32_MAX_EXPO) { /* infinity / anything = infinity */ if (s) res |= AR_STAT_NEGATIVE; *x = *a; x->sign = s; return res | AR_STAT_OVERFLOW; } if (b->expo == 0 && !IS_IEEE32_NZ_COEFF(b)) { if (a->expo == 0 && !IS_IEEE32_NZ_COEFF(a)) { /* zero/zero = quiet NaN */ QNaNIEEE32 (x); return res | AR_STAT_UNDEFINED; } else { /* anything / zero = infinity */ if (s) res |= AR_STAT_NEGATIVE; ZEROIEEE32 (*x); x->sign = s; x->expo = AR_IEEE32_MAX_EXPO + 1; return res | AR_STAT_OVERFLOW; } } /* Test for denorms (they have zero exponents) to determine the * values of the implicit normalization bits; make them explicit. */ if (ar_state_register.ar_denorms_trap && ((!a->expo && IS_IEEE32_NZ_COEFF(a)) || (!b->expo && IS_IEEE32_NZ_COEFF(b)))) { /* operand is a denorm and denorms cause a trap */ x->expo = AR_IEEE32_MAX_EXPO + 1; return res | AR_STAT_UNDEFINED; } y = *a; y_lbits = !!a->expo; ZEROIEEE32 (y2); z = *b; z_lbits = !!b->expo; ZEROIEEE32 (z2); x_lbits = 0; x_expo = a->expo - b->expo + !a->expo - !b->expo + AR_IEEE32_EXPO_BIAS; ZEROIEEE32 (*x); x->sign = s; rbits = 0; /* Handle division by a denormalized value */ if (!b->expo) { while (!z_lbits) { z_lbits = z.coeff0 >> (AR_IEEE32_C0_BITS - 1); SHLEFTIEEE32 (z); x_expo++; } } if (x_expo <= 0) x_expo--; /* Divide by repeated subtraction */ for (i = 0; i < AR_IEEE32_COEFF_BITS + AR_IEEE32_ROUND_BITS + 1; i++) { x_lbits = x->coeff0 >> (AR_IEEE32_C0_BITS - 1); SHLEFTIEEE32 (*x); x->coeff1 |= rbits >> (AR_IEEE32_ROUND_BITS - 1); rbits = (rbits << 1) & MASKR (AR_IEEE32_ROUND_BITS); /* If scaled denominator <= numerator, subtract */ if (z_lbits < y_lbits || z_lbits == y_lbits && (z.coeff0 < y.coeff0 || z.coeff0 == y.coeff0 && (z.coeff1 < y.coeff1 || z.coeff1 == y.coeff1 && (z2.coeff0 < y2.coeff0 || z2.coeff0 == y2.coeff0 && z2.coeff1 <= y2.coeff1)))) { y2.coeff1 = carry = y2.coeff1 + 1 + (z2.coeff1 ^ MASKR (AR_IEEE32_C1_BITS)); carry >>= AR_IEEE32_C1_BITS; y2.coeff0 = carry += y2.coeff0 + (z2.coeff0 ^ MASKR (AR_IEEE32_C0_BITS)); carry >>= AR_IEEE32_C0_BITS; y.coeff1 = carry += y.coeff1 + (z.coeff1 ^ MASKR (AR_IEEE32_C1_BITS)); carry >>= AR_IEEE32_C1_BITS; y.coeff0 = carry += y.coeff0 + (z.coeff0 ^ MASKR (AR_IEEE32_C0_BITS)); carry >>= AR_IEEE32_C0_BITS; y_lbits = (y_lbits + carry + (z_lbits ^ 1)) & 1; rbits |= 1; } SHRIGHTIEEE32_2 (z, z2); z.coeff0 |= z_lbits << (AR_IEEE32_C0_BITS - 1); z_lbits = 0; }
int ar_ifmul32 (AR_IEEE_32 *x, const AR_IEEE_32 *a, const AR_IEEE_32 *b, int roundmode) { int i, res = AR_STAT_OK; unsigned long x_lbits, z_lbits, rbits, carry; signed int x_expo; AR_IEEE_32 x2, y, y2, z; /* If either a or b is a NaN, it's the result. */ if (IS_IEEE32_NaN(a)) { *x = *a; return res | AR_STAT_UNDEFINED; } if (IS_IEEE32_NaN(b)) { *x = *b; return res | AR_STAT_UNDEFINED; } /* Test for infinities */ if (b->expo > AR_IEEE32_MAX_EXPO) if (a->expo == 0 && !IS_IEEE32_NZ_COEFF(a)){ /* zero * inf = quiet NaN */ QNaNIEEE32 (x); return res | AR_STAT_UNDEFINED; } else { /* anything * infinity = infinity */ if (i = a->sign ^ b->sign) res |= AR_STAT_NEGATIVE; *x = *b; x->sign = i; return res | AR_STAT_OVERFLOW; } if (a->expo > AR_IEEE32_MAX_EXPO) if (b->expo == 0 && !IS_IEEE32_NZ_COEFF(b)){ /* infinity * zero = quiet NaN */ QNaNIEEE32 (x); return res | AR_STAT_UNDEFINED; } else { /* infinity * anything = infinity */ if (i = a->sign ^ b->sign) res |= AR_STAT_NEGATIVE; *x = *a; x->sign = i; return res | AR_STAT_OVERFLOW; } /* Test for denorms (they have zero exponents) to determine the * values of the implicit normalization bits; make them explicit. */ if (ar_state_register.ar_denorms_trap && ((!a->expo && IS_IEEE32_NZ_COEFF(a)) || (!b->expo && IS_IEEE32_NZ_COEFF(b)))) { /* operand is a denorm and denorms cause a trap */ x->expo = AR_IEEE32_MAX_EXPO + 1; return res | AR_STAT_UNDEFINED; } ZEROIEEE32 (y); y.coeff1 = !!a->expo; y2 = *a; z = *b; z_lbits = !!b->expo; x_expo = a->expo + b->expo + !a->expo + !b->expo - AR_IEEE32_EXPO_BIAS; if (x_expo <= 0) x_expo--; i = a->sign ^ b->sign; /* Sum the pyramid */ if (z.coeff1 & 1) { x2 = *a; *x = y; } else { ZEROIEEE32 (*x); ZEROIEEE32 (x2); } x->sign = i; x_lbits = z_lbits & y.coeff1; SHLEFTIEEE32_2 (y, y2); SHRIGHTIEEE32 (z); z.coeff0 |= z_lbits << (AR_IEEE32_C0_BITS - 1); for (i = 1; i < AR_IEEE32_COEFF_BITS + 1; i++) { if (z.coeff1 & 1) { carry = 0; ADDIEEE32 (x2, carry, x2, y2); ADDIEEE32 (*x, carry, *x, y); x_lbits += carry; } SHLEFTIEEE32_2 (y, y2); SHRIGHTIEEE32 (z); } /* Extract rounding bits */ rbits = x2.coeff0 >> (AR_IEEE32_C0_BITS - AR_IEEE32_ROUND_BITS); if (x2.coeff0 & MASKR (AR_IEEE32_C0_BITS - AR_IEEE32_ROUND_BITS) | x2.coeff1) rbits |= 1; /* sticky bit */ /* Normalize and round */ return ar_i32norm (x_expo, x_lbits, rbits, x, roundmode); }