2005-04-16 15:20:36 -07:00
/* IEEE754 floating point arithmetic
* double precision : common utilities
*/
/*
* MIPS floating point support
* Copyright ( C ) 1994 - 2000 Algorithmics Ltd .
*
* This program is free software ; you can distribute it and / or modify it
* under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
2014-04-26 01:49:14 +02:00
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-04-16 15:20:36 -07:00
*/
# include "ieee754dp.h"
2014-04-16 01:31:11 +02:00
union ieee754dp ieee754dp_add ( union ieee754dp x , union ieee754dp y )
2005-04-16 15:20:36 -07:00
{
2014-04-26 01:49:14 +02:00
int s ;
2005-04-16 15:20:36 -07:00
COMPXDP ;
COMPYDP ;
EXPLODEXDP ;
EXPLODEYDP ;
2014-04-19 00:36:32 +02:00
ieee754_clearcx ( ) ;
2005-04-16 15:20:36 -07:00
FLUSHXDP ;
FLUSHYDP ;
switch ( CLPAIR ( xc , yc ) ) {
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_QNAN ) :
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_DNORM ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_INF ) :
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2014-04-25 03:19:57 +02:00
return ieee754dp_nanxcpt ( ieee754dp_indef ( ) ) ;
2005-04-16 15:20:36 -07:00
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_QNAN ) :
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_QNAN ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_QNAN ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_QNAN ) :
return y ;
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_QNAN ) :
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_DNORM ) :
case CLPAIR ( IEEE754_CLASS_QNAN , IEEE754_CLASS_INF ) :
return x ;
2014-04-26 01:49:14 +02:00
/*
* Infinity handling
*/
2005-04-16 15:20:36 -07:00
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_INF ) :
if ( xs = = ys )
return x ;
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2014-04-25 03:19:57 +02:00
return ieee754dp_indef ( ) ;
2005-04-16 15:20:36 -07:00
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_INF ) :
return y ;
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_DNORM ) :
return x ;
2014-04-26 01:49:14 +02:00
/*
* Zero handling
*/
2005-04-16 15:20:36 -07:00
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_ZERO ) :
if ( xs = = ys )
return x ;
else
2014-04-26 01:49:14 +02:00
return ieee754dp_zero ( ieee754_csr . rm = = IEEE754_RD ) ;
2005-04-16 15:20:36 -07:00
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_ZERO ) :
return x ;
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_DNORM ) :
return y ;
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_DNORM ) :
DPDNORMX ;
/* FALL THROUGH */
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_DNORM ) :
DPDNORMY ;
break ;
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_NORM ) :
DPDNORMX ;
break ;
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_NORM ) :
break ;
}
assert ( xm & DP_HIDDEN_BIT ) ;
assert ( ym & DP_HIDDEN_BIT ) ;
2014-04-26 01:49:14 +02:00
/*
* Provide guard , round and stick bit space .
*/
2005-04-16 15:20:36 -07:00
xm < < = 3 ;
ym < < = 3 ;
if ( xe > ye ) {
2014-04-26 01:49:14 +02:00
/*
* Have to shift y fraction right to align .
2005-04-16 15:20:36 -07:00
*/
2014-04-26 01:49:14 +02:00
s = xe - ye ;
2005-04-16 15:20:36 -07:00
ym = XDPSRS ( ym , s ) ;
ye + = s ;
} else if ( ye > xe ) {
2014-04-26 01:49:14 +02:00
/*
* Have to shift x fraction right to align .
2005-04-16 15:20:36 -07:00
*/
2014-04-26 01:49:14 +02:00
s = ye - xe ;
2005-04-16 15:20:36 -07:00
xm = XDPSRS ( xm , s ) ;
xe + = s ;
}
assert ( xe = = ye ) ;
assert ( xe < = DP_EMAX ) ;
if ( xs = = ys ) {
2014-04-26 01:49:14 +02:00
/*
* Generate 28 bit result of adding two 27 bit numbers
* leaving result in xm , xs and xe .
2005-04-16 15:20:36 -07:00
*/
xm = xm + ym ;
xe = xe ;
xs = xs ;
2014-04-22 15:51:55 +02:00
if ( xm > > ( DP_FBITS + 1 + 3 ) ) { /* carry out */
2005-04-16 15:20:36 -07:00
xm = XDPSRS1 ( xm ) ;
xe + + ;
}
} else {
if ( xm > = ym ) {
xm = xm - ym ;
xe = xe ;
xs = xs ;
} else {
xm = ym - xm ;
xe = xe ;
xs = ys ;
}
if ( xm = = 0 )
2014-04-26 01:49:14 +02:00
return ieee754dp_zero ( ieee754_csr . rm = = IEEE754_RD ) ;
2005-04-16 15:20:36 -07:00
2014-04-26 01:49:14 +02:00
/*
* Normalize to rounding precision .
*/
2014-04-22 15:51:55 +02:00
while ( ( xm > > ( DP_FBITS + 3 ) ) = = 0 ) {
2005-04-16 15:20:36 -07:00
xm < < = 1 ;
xe - - ;
}
}
2014-04-25 03:19:57 +02:00
return ieee754dp_format ( xs , xe , xm ) ;
2005-04-16 15:20:36 -07:00
}