2005-04-16 15:20:36 -07: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 . ,
* 59 Temple Place - Suite 330 , Boston MA 02111 - 1307 , USA .
*
* # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
*/
# include "ieee754sp.h"
s64 ieee754sp_tlong ( ieee754sp x )
{
COMPXDP ; /* <-- need 64-bit mantissa tmp */
CLEARCX ;
EXPLODEXSP ;
FLUSHXSP ;
switch ( xc ) {
case IEEE754_CLASS_SNAN :
case IEEE754_CLASS_QNAN :
case IEEE754_CLASS_INF :
SETCX ( IEEE754_INVALID_OPERATION ) ;
return ieee754di_xcpt ( ieee754di_indef ( ) , " sp_tlong " , x ) ;
case IEEE754_CLASS_ZERO :
return 0 ;
case IEEE754_CLASS_DNORM :
case IEEE754_CLASS_NORM :
break ;
}
if ( xe > = 63 ) {
/* look for valid corner case */
if ( xe = = 63 & & xs & & xm = = SP_HIDDEN_BIT )
return - 0x8000000000000000LL ;
/* Set invalid. We will only use overflow for floating
point overflow */
SETCX ( IEEE754_INVALID_OPERATION ) ;
return ieee754di_xcpt ( ieee754di_indef ( ) , " sp_tlong " , x ) ;
}
/* oh gawd */
if ( xe > SP_MBITS ) {
xm < < = xe - SP_MBITS ;
} else if ( xe < SP_MBITS ) {
u32 residue ;
int round ;
int sticky ;
int odd ;
if ( xe < - 1 ) {
residue = xm ;
round = 0 ;
sticky = residue ! = 0 ;
xm = 0 ;
2010-05-23 21:52:10 +02:00
} else {
2005-04-16 15:20:36 -07:00
residue = xm < < ( 32 - SP_MBITS + xe ) ;
round = ( residue > > 31 ) ! = 0 ;
sticky = ( residue < < 1 ) ! = 0 ;
xm > > = SP_MBITS - xe ;
}
odd = ( xm & 0x1 ) ! = 0x0 ;
switch ( ieee754_csr . rm ) {
case IEEE754_RN :
if ( round & & ( sticky | | odd ) )
xm + + ;
break ;
case IEEE754_RZ :
break ;
case IEEE754_RU : /* toward +Infinity */
if ( ( round | | sticky ) & & ! xs )
xm + + ;
break ;
case IEEE754_RD : /* toward -Infinity */
if ( ( round | | sticky ) & & xs )
xm + + ;
break ;
}
if ( ( xm > > 63 ) ! = 0 ) {
/* This can happen after rounding */
SETCX ( IEEE754_INVALID_OPERATION ) ;
return ieee754di_xcpt ( ieee754di_indef ( ) , " sp_tlong " , x ) ;
}
if ( round | | sticky )
SETCX ( IEEE754_INEXACT ) ;
}
if ( xs )
return - xm ;
else
return xm ;
}
u64 ieee754sp_tulong ( ieee754sp x )
{
ieee754sp hb = ieee754sp_1e63 ( ) ;
/* what if x < 0 ?? */
if ( ieee754sp_lt ( x , hb ) )
return ( u64 ) ieee754sp_tlong ( x ) ;
return ( u64 ) ieee754sp_tlong ( ieee754sp_sub ( x , hb ) ) |
( 1ULL < < 63 ) ;
}