2005-04-17 02:20:36 +04: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 03:49:14 +04:00
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-04-17 02:20:36 +04:00
*/
# include "ieee754dp.h"
2014-04-16 03:31:11 +04:00
union ieee754dp ieee754dp_mul ( union ieee754dp x , union ieee754dp y )
2005-04-17 02:20:36 +04:00
{
2014-04-26 03:49:14 +04:00
int re ;
int rs ;
u64 rm ;
unsigned lxm ;
unsigned hxm ;
unsigned lym ;
unsigned hym ;
u64 lrm ;
u64 hrm ;
u64 t ;
u64 at ;
2005-04-17 02:20:36 +04:00
COMPXDP ;
COMPYDP ;
EXPLODEXDP ;
EXPLODEYDP ;
2014-04-19 02:36:32 +04:00
ieee754_clearcx ( ) ;
2005-04-17 02:20:36 +04:00
FLUSHXDP ;
FLUSHYDP ;
switch ( CLPAIR ( xc , yc ) ) {
case CLPAIR ( IEEE754_CLASS_QNAN , 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 ) :
2015-04-04 01:25:34 +03:00
return ieee754dp_nanxcpt ( y ) ;
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_SNAN ) :
case CLPAIR ( IEEE754_CLASS_SNAN , IEEE754_CLASS_QNAN ) :
2005-04-17 02:20:36 +04:00
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 ) :
2015-04-04 01:25:34 +03:00
return ieee754dp_nanxcpt ( x ) ;
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_ZERO ) :
case CLPAIR ( IEEE754_CLASS_ZERO , 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 ieee754dp_indef ( ) ;
2005-04-17 02:20:36 +04:00
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_INF ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_DNORM ) :
case CLPAIR ( IEEE754_CLASS_INF , IEEE754_CLASS_INF ) :
return ieee754dp_inf ( xs ^ ys ) ;
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_NORM ) :
case CLPAIR ( IEEE754_CLASS_ZERO , IEEE754_CLASS_DNORM ) :
case CLPAIR ( IEEE754_CLASS_NORM , IEEE754_CLASS_ZERO ) :
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_ZERO ) :
return ieee754dp_zero ( xs ^ ys ) ;
case CLPAIR ( IEEE754_CLASS_DNORM , IEEE754_CLASS_DNORM ) :
DPDNORMX ;
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 ;
}
2011-03-31 05:57:33 +04:00
/* rm = xm * ym, re = xe+ye basically */
2005-04-17 02:20:36 +04:00
assert ( xm & DP_HIDDEN_BIT ) ;
assert ( ym & DP_HIDDEN_BIT ) ;
2014-04-26 03:49:14 +04:00
re = xe + ye ;
rs = xs ^ ys ;
/* shunt to top of word */
xm < < = 64 - ( DP_FBITS + 1 ) ;
ym < < = 64 - ( DP_FBITS + 1 ) ;
2005-04-17 02:20:36 +04:00
2014-04-26 03:49:14 +04:00
/*
2016-04-21 16:04:52 +03:00
* Multiply 64 bits xm , ym to give high 64 bits rm with stickness .
2014-04-26 03:49:14 +04:00
*/
2005-04-17 02:20:36 +04:00
2014-04-26 03:49:14 +04:00
/* 32 * 32 => 64 */
2007-10-12 02:46:15 +04:00
# define DPXMULT(x, y) ((u64)(x) * (u64)y)
2005-04-17 02:20:36 +04:00
2014-04-26 03:49:14 +04:00
lxm = xm ;
hxm = xm > > 32 ;
lym = ym ;
hym = ym > > 32 ;
lrm = DPXMULT ( lxm , lym ) ;
hrm = DPXMULT ( hxm , hym ) ;
t = DPXMULT ( lxm , hym ) ;
at = lrm + ( t < < 32 ) ;
hrm + = at < lrm ;
lrm = at ;
hrm = hrm + ( t > > 32 ) ;
t = DPXMULT ( hxm , lym ) ;
at = lrm + ( t < < 32 ) ;
hrm + = at < lrm ;
lrm = at ;
hrm = hrm + ( t > > 32 ) ;
rm = hrm | ( lrm ! = 0 ) ;
/*
* Sticky shift down to normal rounding precision .
*/
if ( ( s64 ) rm < 0 ) {
rm = ( rm > > ( 64 - ( DP_FBITS + 1 + 3 ) ) ) |
( ( rm < < ( DP_FBITS + 1 + 3 ) ) ! = 0 ) ;
2016-04-21 16:04:53 +03:00
re + + ;
2014-04-26 03:49:14 +04:00
} else {
rm = ( rm > > ( 64 - ( DP_FBITS + 1 + 3 + 1 ) ) ) |
( ( rm < < ( DP_FBITS + 1 + 3 + 1 ) ) ! = 0 ) ;
2005-04-17 02:20:36 +04:00
}
2014-04-26 03:49:14 +04:00
assert ( rm & ( DP_HIDDEN_BIT < < 3 ) ) ;
return ieee754dp_format ( rs , re , rm ) ;
2005-04-17 02:20:36 +04:00
}