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
int ieee754dp_tint ( union ieee754dp x )
2005-04-16 15:20:36 -07:00
{
2014-04-26 01:49:14 +02:00
u64 residue ;
int round ;
int sticky ;
int odd ;
2005-04-16 15:20:36 -07:00
COMPXDP ;
2014-04-19 00:36:32 +02:00
ieee754_clearcx ( ) ;
2005-04-16 15:20:36 -07:00
EXPLODEXDP ;
FLUSHXDP ;
switch ( xc ) {
case IEEE754_CLASS_SNAN :
case IEEE754_CLASS_QNAN :
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2014-04-25 03:19:57 +02:00
return ieee754si_indef ( ) ;
2014-04-26 01:49:14 +02:00
2015-11-13 00:47:28 +00:00
case IEEE754_CLASS_INF :
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
return ieee754si_overflow ( xs ) ;
2005-04-16 15:20:36 -07:00
case IEEE754_CLASS_ZERO :
return 0 ;
2014-04-26 01:49:14 +02:00
2005-04-16 15:20:36 -07:00
case IEEE754_CLASS_DNORM :
case IEEE754_CLASS_NORM :
break ;
}
if ( xe > 31 ) {
/* Set invalid. We will only use overflow for floating
point overflow */
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2015-11-13 00:47:28 +00:00
return ieee754si_overflow ( xs ) ;
2005-04-16 15:20:36 -07:00
}
/* oh gawd */
2014-04-22 15:51:55 +02:00
if ( xe > DP_FBITS ) {
xm < < = xe - DP_FBITS ;
} else if ( xe < DP_FBITS ) {
2005-04-16 15:20:36 -07:00
if ( xe < - 1 ) {
residue = xm ;
round = 0 ;
sticky = residue ! = 0 ;
xm = 0 ;
2010-05-23 21:52:06 +02:00
} else {
2014-04-22 15:51:55 +02:00
residue = xm < < ( 64 - DP_FBITS + xe ) ;
2005-04-16 15:20:36 -07:00
round = ( residue > > 63 ) ! = 0 ;
sticky = ( residue < < 1 ) ! = 0 ;
2014-04-22 15:51:55 +02:00
xm > > = DP_FBITS - xe ;
2005-04-16 15:20:36 -07:00
}
/* Note: At this point upper 32 bits of xm are guaranteed
to be zero */
odd = ( xm & 0x1 ) ! = 0x0 ;
switch ( ieee754_csr . rm ) {
2014-04-30 11:21:55 +02:00
case FPU_CSR_RN :
2005-04-16 15:20:36 -07:00
if ( round & & ( sticky | | odd ) )
xm + + ;
break ;
2014-04-30 11:21:55 +02:00
case FPU_CSR_RZ :
2005-04-16 15:20:36 -07:00
break ;
2014-04-30 11:21:55 +02:00
case FPU_CSR_RU : /* toward +Infinity */
2005-04-16 15:20:36 -07:00
if ( ( round | | sticky ) & & ! xs )
xm + + ;
break ;
2014-04-30 11:21:55 +02:00
case FPU_CSR_RD : /* toward -Infinity */
2005-04-16 15:20:36 -07:00
if ( ( round | | sticky ) & & xs )
xm + + ;
break ;
}
/* look for valid corner case 0x80000000 */
if ( ( xm > > 31 ) ! = 0 & & ( xs = = 0 | | xm ! = 0x80000000 ) ) {
/* This can happen after rounding */
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2015-11-13 00:47:28 +00:00
return ieee754si_overflow ( xs ) ;
2005-04-16 15:20:36 -07:00
}
if ( round | | sticky )
2014-04-19 00:36:32 +02:00
ieee754_setcx ( IEEE754_INEXACT ) ;
2005-04-16 15:20:36 -07:00
}
if ( xs )
return - xm ;
else
return xm ;
}