2005-04-17 02:20:36 +04:00
/*
NetWinder Floating Point Emulator
( c ) Rebel . COM , 1998 , 1999
( c ) Philip Blundell , 2001
Direct questions , comments to Scott Bambrough < scottb @ netwinder . org >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "fpa11.h"
# include "softfloat.h"
# include "fpopcode.h"
float32 float32_exp ( float32 Fm ) ;
float32 float32_ln ( float32 Fm ) ;
float32 float32_sin ( float32 rFm ) ;
float32 float32_cos ( float32 rFm ) ;
float32 float32_arcsin ( float32 rFm ) ;
float32 float32_arctan ( float32 rFm ) ;
float32 float32_log ( float32 rFm ) ;
float32 float32_tan ( float32 rFm ) ;
float32 float32_arccos ( float32 rFm ) ;
float32 float32_pow ( float32 rFn , float32 rFm ) ;
float32 float32_pol ( float32 rFn , float32 rFm ) ;
2005-08-03 22:49:17 +04:00
static float32 float32_rsf ( struct roundingData * roundData , float32 rFn , float32 rFm )
2005-04-17 02:20:36 +04:00
{
2005-08-03 22:49:17 +04:00
return float32_sub ( roundData , rFm , rFn ) ;
2005-04-17 02:20:36 +04:00
}
2005-08-03 22:49:17 +04:00
static float32 float32_rdv ( struct roundingData * roundData , float32 rFn , float32 rFm )
2005-04-17 02:20:36 +04:00
{
2005-08-03 22:49:17 +04:00
return float32_div ( roundData , rFm , rFn ) ;
2005-04-17 02:20:36 +04:00
}
2005-08-03 22:49:17 +04:00
static float32 ( * const dyadic_single [ 16 ] ) ( struct roundingData * , float32 rFn , float32 rFm ) = {
2005-04-17 02:20:36 +04:00
[ ADF_CODE > > 20 ] = float32_add ,
[ MUF_CODE > > 20 ] = float32_mul ,
[ SUF_CODE > > 20 ] = float32_sub ,
[ RSF_CODE > > 20 ] = float32_rsf ,
[ DVF_CODE > > 20 ] = float32_div ,
[ RDF_CODE > > 20 ] = float32_rdv ,
[ RMF_CODE > > 20 ] = float32_rem ,
[ FML_CODE > > 20 ] = float32_mul ,
[ FDV_CODE > > 20 ] = float32_div ,
[ FRD_CODE > > 20 ] = float32_rdv ,
} ;
2005-08-03 22:49:17 +04:00
static float32 float32_mvf ( struct roundingData * roundData , float32 rFm )
2005-04-17 02:20:36 +04:00
{
return rFm ;
}
2005-08-03 22:49:17 +04:00
static float32 float32_mnf ( struct roundingData * roundData , float32 rFm )
2005-04-17 02:20:36 +04:00
{
return rFm ^ 0x80000000 ;
}
2005-08-03 22:49:17 +04:00
static float32 float32_abs ( struct roundingData * roundData , float32 rFm )
2005-04-17 02:20:36 +04:00
{
return rFm & 0x7fffffff ;
}
2005-08-03 22:49:17 +04:00
static float32 ( * const monadic_single [ 16 ] ) ( struct roundingData * , float32 rFm ) = {
2005-04-17 02:20:36 +04:00
[ MVF_CODE > > 20 ] = float32_mvf ,
[ MNF_CODE > > 20 ] = float32_mnf ,
[ ABS_CODE > > 20 ] = float32_abs ,
[ RND_CODE > > 20 ] = float32_round_to_int ,
[ URD_CODE > > 20 ] = float32_round_to_int ,
[ SQT_CODE > > 20 ] = float32_sqrt ,
[ NRM_CODE > > 20 ] = float32_mvf ,
} ;
2005-08-03 22:49:17 +04:00
unsigned int SingleCPDO ( struct roundingData * roundData , const unsigned int opcode , FPREG * rFd )
2005-04-17 02:20:36 +04:00
{
FPA11 * fpa11 = GET_FPA11 ( ) ;
float32 rFm ;
unsigned int Fm , opc_mask_shift ;
Fm = getFm ( opcode ) ;
if ( CONSTANT_FM ( opcode ) ) {
rFm = getSingleConstant ( Fm ) ;
} else if ( fpa11 - > fType [ Fm ] = = typeSingle ) {
rFm = fpa11 - > fpreg [ Fm ] . fSingle ;
} else {
return 0 ;
}
opc_mask_shift = ( opcode & MASK_ARITHMETIC_OPCODE ) > > 20 ;
if ( ! MONADIC_INSTRUCTION ( opcode ) ) {
unsigned int Fn = getFn ( opcode ) ;
float32 rFn ;
if ( fpa11 - > fType [ Fn ] = = typeSingle & &
dyadic_single [ opc_mask_shift ] ) {
rFn = fpa11 - > fpreg [ Fn ] . fSingle ;
2005-08-03 22:49:17 +04:00
rFd - > fSingle = dyadic_single [ opc_mask_shift ] ( roundData , rFn , rFm ) ;
2005-04-17 02:20:36 +04:00
} else {
return 0 ;
}
} else {
if ( monadic_single [ opc_mask_shift ] ) {
2005-08-03 22:49:17 +04:00
rFd - > fSingle = monadic_single [ opc_mask_shift ] ( roundData , rFm ) ;
2005-04-17 02:20:36 +04:00
} else {
return 0 ;
}
}
return 1 ;
}