__quad_mag64.s revision 7c478bd95313f5f23a4c958a745db2134aa03244
!
!
!
!
!
!
!
.ident "%Z%%M% %I% %E% SMI"
! /*
! * This file contains __quad_mag_add and __quad_mag_sub, the core
! * of the quad precision add and subtract operations.
! */
.file "__quad_mag64.s"
#include <sys/asm_linkage.h>
! union longdouble {
! struct {
! unsigned int msw;
! unsigned int frac2;
! unsigned int frac3;
! unsigned int frac4;
! } l;
! struct {
! unsigned long msll;
! unsigned long frac;
! } ll;
! long double d;
! };
!
! /*
! * __quad_mag_add(x, y, z, fsr)
! *
! * Sets *z = *x + *y, rounded according to the rounding mode in *fsr,
! * and updates the current exceptions in *fsr. This routine assumes
! * *x and *y are finite, with the same sign (i.e., an addition of
! * magnitudes), |*x| >= |*y|, and *z already has its sign bit set.
! */
! void
! union longdouble *z, unsigned int *fsr)
! {
! int e, uflo;
!
! /* get the leading significand double-words and exponents */
! if (ex == 0)
! ex = 1;
! else
! lx |= 0x0001000000000000ul;
!
! if (ey == 0)
! ey = 1;
! else
! ly |= 0x0001000000000000ul;
!
! /* prenormalize y */
! if (e >= 114) {
! } else {
! if (e >= 64) {
! ly = 0;
! e -= 64;
! }
! if (e) {
! ly >>= e;
! }
!
! /* add, propagating carries */
! lx++;
!
! /* postnormalize */
! if (lx >= 0x0002000000000000ul) {
! lx >>= 1;
! ex++;
! }
! }
!
! /* keep track of whether the result before rounding is tiny */
!
! /* get the rounding mode, fudging directed rounding modes
! as though the result were positive */
! if (z->l.msw)
!
! /* see if we need to round */
!
! /* round up if necessary */
! if (++frac == 0)
! if (++lx >= 0x0002000000000000ul) {
! lx >>= 1;
! ex++;
! }
! }
! }
!
! /* check for overflow */
! if (ex >= 0x7fff) {
! /* store the default overflowed result */
! z->l.msw |= 0x7fff0000;
! z->l.frac2 = 0;
! } else {
! z->l.msw |= 0x7ffeffff;
! z->l.frac2 = 0xffffffff;
! }
! } else {
! /* store the result */
! if (lx >= 0x0001000000000000ul)
!
! /* if the pre-rounded result was tiny and underflow trapping
! is enabled, simulate underflow */
! }
! }
1:
2:
1:
2:
3:
4:
5:
1:
2:
1:
2:
1:
2:
1:
2:
3:
! /*
! * __quad_mag_sub(x, y, z, fsr)
! *
! * Sets *z = *x - *y, rounded according to the rounding mode in *fsr,
! * and updates the current exceptions in *fsr. This routine assumes
! * *x and *y are finite, with opposite signs (i.e., a subtraction of
! * magnitudes), |*x| >= |*y|, and *z already has its sign bit set.
! */
! void
! union longdouble *z, unsigned int *fsr)
! {
! int e;
!
! /* get the leading significand double-words and exponents */
! if (ex == 0)
! ex = 1;
! else
! lx |= 0x0001000000000000ul;
!
! if (ey == 0)
! ey = 1;
! else
! ly |= 0x0001000000000000ul;
!
! /* prenormalize y */
! if (e > 114) {
! } else {
! if (e >= 64) {
! ly = 0;
! e -= 64;
! }
! if (e > 1) {
! ly >>= e;
! } else if (e == 1) {
! ly >>= 1;
! }
! }
!
! /* complement guard, round, and sticky as need be */
! gr <<= 1;
! if (sticky)
! gr |= 1;
! if (gr)
! if (++frac == 0)
! ly++;
!
! /* subtract, propagating borrows */
! lx--;
!
! /* get the rounding mode */
!
! /* handle zero result */
! return;
! }
!
! /* postnormalize */
! if (lx < 0x0001000000000000ul) {
! /* if cancellation occurred or the exponent is 1,
! the result is exact */
! ex > 64) {
! gr = 0;
! ex -= 64;
! }
! gr = 0;
! ex--;
! }
! if (lx >= 0x0001000000000000ul)
!
! /* if the result is tiny and underflow trapping is
! enabled, simulate underflow */
! return;
! }
!
! /* otherwise we only borrowed one place */
! gr &= 3;
! ex--;
! }
! else
!
! /* fudge directed rounding modes as though the result were positive */
! if (z->l.msw)
!
! /* see if we need to round */
! if (gr) {
!
! /* round up if necessary */
! if (++frac == 0)
! if (++lx >= 0x0002000000000000ul) {
! lx >>= 1;
! ex++;
! }
! }
! }
!
! /* store the result */
! }
1:
2:
1:
2:
3:
4:
1:
2:
1:
1:
5:
1:
1:
1:
1:
1:
1:
1:
2:
1:
2:
1: