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 . ,
* 59 Temple Place - Suite 330 , Boston MA 02111 - 1307 , USA .
*
* # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
*/
# include "ieee754sp.h"
2014-04-16 03:31:11 +04:00
union ieee754sp ieee754sp_mul ( union ieee754sp x , union ieee754sp y )
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 ) ;
2005-04-17 02:20:36 +04:00
return ieee754sp_nanxcpt ( ieee754sp_indef ( ) , " mul " , x , y ) ;
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 ;
/* Infinity handling */
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 ) ;
2005-04-17 02:20:36 +04:00
return ieee754sp_xcpt ( ieee754sp_indef ( ) , " mul " , x , y ) ;
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 ieee754sp_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 ieee754sp_zero ( xs ^ ys ) ;
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 ;
}
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 & SP_HIDDEN_BIT ) ;
assert ( ym & SP_HIDDEN_BIT ) ;
{
int re = xe + ye ;
int rs = xs ^ ys ;
unsigned rm ;
/* shunt to top of word */
2014-04-22 17:51:55 +04:00
xm < < = 32 - ( SP_FBITS + 1 ) ;
ym < < = 32 - ( SP_FBITS + 1 ) ;
2005-04-17 02:20:36 +04:00
/* multiply 32bits xm,ym to give high 32bits rm with stickness
*/
{
unsigned short lxm = xm & 0xffff ;
unsigned short hxm = xm > > 16 ;
unsigned short lym = ym & 0xffff ;
unsigned short hym = ym > > 16 ;
unsigned lrm ;
unsigned hrm ;
lrm = lxm * lym ; /* 16 * 16 => 32 */
hrm = hxm * hym ; /* 16 * 16 => 32 */
{
2013-01-22 15:59:30 +04:00
unsigned t = lxm * hym ; /* 16 * 16 => 32 */
2005-04-17 02:20:36 +04:00
{
unsigned at = lrm + ( t < < 16 ) ;
hrm + = at < lrm ;
lrm = at ;
}
hrm = hrm + ( t > > 16 ) ;
}
{
2013-01-22 15:59:30 +04:00
unsigned t = hxm * lym ; /* 16 * 16 => 32 */
2005-04-17 02:20:36 +04:00
{
unsigned at = lrm + ( t < < 16 ) ;
hrm + = at < lrm ;
lrm = at ;
}
hrm = hrm + ( t > > 16 ) ;
}
rm = hrm | ( lrm ! = 0 ) ;
}
/*
* sticky shift down to normal rounding precision
*/
if ( ( int ) rm < 0 ) {
2014-04-22 17:51:55 +04:00
rm = ( rm > > ( 32 - ( SP_FBITS + 1 + 3 ) ) ) |
( ( rm < < ( SP_FBITS + 1 + 3 ) ) ! = 0 ) ;
2005-04-17 02:20:36 +04:00
re + + ;
} else {
2014-04-22 17:51:55 +04:00
rm = ( rm > > ( 32 - ( SP_FBITS + 1 + 3 + 1 ) ) ) |
( ( rm < < ( SP_FBITS + 1 + 3 + 1 ) ) ! = 0 ) ;
2005-04-17 02:20:36 +04:00
}
assert ( rm & ( SP_HIDDEN_BIT < < 3 ) ) ;
SPNORMRET2 ( rs , re , rm , " mul " , x , y ) ;
}
}