2005-04-17 02:20:36 +04:00
/* IEEE754 floating point arithmetic
* single precision
*/
/*
* 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 03:49:14 +04:00
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-04-17 02:20:36 +04:00
*/
# include "ieee754sp.h"
2014-04-16 03:31:11 +04:00
union ieee754sp ieee754sp_sub ( union ieee754sp x , union ieee754sp y )
2005-04-17 02:20:36 +04:00
{
2014-04-26 03:49:14 +04:00
int s ;
2005-04-17 02:20:36 +04:00
COMPXSP ;
COMPYSP ;
EXPLODEXSP ;
EXPLODEYSP ;
2014-04-19 02:36:32 +04:00
ieee754_clearcx ( ) ;
2005-04-17 02:20:36 +04:00
FLUSHXSP ;
FLUSHYSP ;
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 02:36:32 +04:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2014-04-25 05:19:57 +04:00
return ieee754sp_nanxcpt ( ieee754sp_indef ( ) ) ;
2005-04-17 02:20:36 +04: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 03:49:14 +04:00
/*
* Infinity handling
*/
2005-04-17 02:20:36 +04:00
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_INF ) :
if ( xs ! = ys )
return x ;
2014-04-19 02:36:32 +04:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2014-04-25 05:19:57 +04:00
return ieee754sp_indef ( ) ;
2005-04-17 02:20:36 +04:00
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_INF ) :
return ieee754sp_inf ( ys ^ 1 ) ;
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 03:49:14 +04:00
/*
* Zero handling
*/
2005-04-17 02:20:36 +04:00
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_ZERO ) :
if ( xs ! = ys )
return x ;
else
2014-04-30 13:21:55 +04:00
return ieee754sp_zero ( ieee754_csr . rm = = FPU_CSR_RD ) ;
2005-04-17 02:20:36 +04: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 ) :
/* quick fix up */
2014-04-22 18:02:03 +04:00
SPSIGN ( y ) ^ = 1 ;
2005-04-17 02:20:36 +04:00
return y ;
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_DNORM ) :
SPDNORMX ;
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_DNORM ) :
SPDNORMY ;
break ;
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_NORM ) :
SPDNORMX ;
break ;
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_NORM ) :
break ;
}
/* flip sign of y and handle as add */
ys ^ = 1 ;
assert ( xm & SP_HIDDEN_BIT ) ;
assert ( ym & SP_HIDDEN_BIT ) ;
/* provide guard,round and stick bit space */
xm < < = 3 ;
ym < < = 3 ;
if ( xe > ye ) {
2014-04-26 03:49:14 +04:00
/*
* have to shift y fraction right to align
2005-04-17 02:20:36 +04:00
*/
2014-04-26 03:49:14 +04:00
s = xe - ye ;
2005-04-17 02:20:36 +04:00
SPXSRSYn ( s ) ;
} else if ( ye > xe ) {
2014-04-26 03:49:14 +04:00
/*
* have to shift x fraction right to align
2005-04-17 02:20:36 +04:00
*/
2014-04-26 03:49:14 +04:00
s = ye - xe ;
2005-04-17 02:20:36 +04:00
SPXSRSXn ( s ) ;
}
assert ( xe = = ye ) ;
assert ( xe < = SP_EMAX ) ;
if ( xs = = ys ) {
/* generate 28 bit result of adding two 27 bit numbers
*/
xm = xm + ym ;
xe = xe ;
xs = xs ;
2014-04-22 17:51:55 +04:00
if ( xm > > ( SP_FBITS + 1 + 3 ) ) { /* carry out */
2005-04-17 02:20:36 +04:00
SPXSRSX1 ( ) ; /* shift preserving sticky */
}
} else {
if ( xm > = ym ) {
xm = xm - ym ;
xe = xe ;
xs = xs ;
} else {
xm = ym - xm ;
xe = xe ;
xs = ys ;
}
if ( xm = = 0 ) {
2014-04-30 13:21:55 +04:00
if ( ieee754_csr . rm = = FPU_CSR_RD )
2005-04-17 02:20:36 +04:00
return ieee754sp_zero ( 1 ) ; /* round negative inf. => sign = -1 */
else
return ieee754sp_zero ( 0 ) ; /* other round modes => sign = 1 */
}
/* normalize to rounding precision
*/
2014-04-22 17:51:55 +04:00
while ( ( xm > > ( SP_FBITS + 3 ) ) = = 0 ) {
2005-04-17 02:20:36 +04:00
xm < < = 1 ;
xe - - ;
}
}
2014-04-25 05:19:57 +04:00
return ieee754sp_format ( xs , xe , xm ) ;
2005-04-17 02:20:36 +04:00
}