* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: fpsim_n2.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named 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 work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
/****************************************************************************
* fpsim_n2.c -- Floating-point Simulation Library for SPARC (Niagara2)
* Robert Rethemeyer - Sun Microsystems, Inc.
* Design -- dynamically loaded shared object; compile with C or C++.
* Models FP instruction behavior according to N2 PRM Appendix I.
* The general strategy is to use the SPARC FP instructions
* while filtering out the cases where N2 requires exceptions
* but Solaris would simulate the operation (e.g. subnormals).
* (c) COPYRIGHT 2005-2006 Sun Microsystems, Inc.
* Sun Confidential: Sun SSG Only
***************************************************************************/
/*********************************************************************
* ATTENTION: This code is part of a library shared by multiple
* projects. DO NOT MAKE CHANGES TO THIS CODE WITHIN YOUR PROJECT.
* Instead, contact the owner/maintainer of the library, currently:
* Robert.Rethemeyer@Sun.COM +1-408-616-5717 (x45717)
* Systems Group: TVT: FrontEnd Technologies
* The CVS source code repository for the library is at:
* /import/ftap-blimp1/cvs/fpsim
* DO NOT COMMIT CHANGES TO THAT REPOSITORY: contact the maintainer.
********************************************************************/
static const char cvsid
[] =
"$Id: fpsim_n2.c,v 1.6 2006/12/07 20:52:04 bobsmail Exp $";
#include "fpsim_support.h"
static int dissect_double( double fpnum
, fpdouble
* data
, int std
, int* exc
);
static int dissect_single( float fpnum
, fpsingle
* data
, int std
, int* exc
);
static void overflow( void* rslt
, int dbl
, int rm
, int si
);
#define FSR_NS 0x00400000 /*FSR nonstandard bit*/
#define GSR_IM 0x08000000 /*GSR interval mode bit*/
#define STDONLY 1 /*Standard mode only*/
#define STDMODE(FSR,GSR) ((((FSR>>22)^1)|(GSR>>27)) & 1)
#define RNDMODE(FSR,GSR) (int)(((GSR & GSR_IM) ? (GSR>>25) : (FSR>>30)) & 3)
/*===========================================================================*/
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_faddd( const double* p_op1
, const double* p_op2
, double* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_double(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
&&(fp_subnormal
==type1
|| fp_subnormal
==type2
))
if(type1
>=fp_infinity
|| type2
>=fp_infinity
) exc
= 0;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_faddd(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_double(result
, &res
, STDONLY
, NULL
);
if(stdmode
) return FPX_UN
;
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)res
.sign
<< 63;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fsubd( const double* p_op1
, const double* p_op2
, double* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_double(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
&&(fp_subnormal
==type1
|| fp_subnormal
==type2
))
if(type1
>=fp_infinity
|| type2
>=fp_infinity
) exc
= 0;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fsubd(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_double(result
, &res
, STDONLY
, NULL
);
if(stdmode
) return FPX_UN
;
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)res
.sign
<< 63;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fmuld( const double* p_op1
, const double* p_op2
, double* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int scr
[2], exc1
=0, exc2
=0;
int type1
= dissect_double(*p_op1
, &op1
, stdmode
, &exc1
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc2
);
int er
= op1
.exp
+ op2
.exp
- 1023;
int si
= op1
.sign
^ op2
.sign
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
if((fp_subnormal
==type1
&& type2
<fp_infinity
&& type2
!=fp_zero
)
|| (fp_subnormal
==type2
&& type1
<fp_infinity
&& type1
!=fp_zero
))
if((er
> -54) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)si
<< 63;
// some operands preclude setting NX for flushed subnormal
|| (fp_zero
==type1
&& 0==exc1
) // either op exactly zero?
|| (fp_zero
==type2
&& 0==exc2
)) exc
= 0; // cancel NX
exc
|= asm_fmuld(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_double(result
, &res
, STDONLY
, NULL
);
&& er
<= 0) //subnormal result?
if((er
> -54) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)si
<< 63;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fdivd( const double* p_op1
, const double* p_op2
, double* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_double(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
int er
= op1
.exp
- op2
.exp
+ 1023 - 1;
int si
= op1
.sign
^ op2
.sign
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
if((fp_subnormal
==type1
&& type2
<fp_infinity
&& type2
!=fp_zero
)
|| (fp_subnormal
==type2
&& type1
<fp_infinity
&& type1
!=fp_zero
))
if(fp_normal
== type1
) frac1
|= 0x0010000000000000;
if(fp_normal
== type2
) frac2
|= 0x0010000000000000;
if(ef
> 2047) // **PRM error now frozen in HW** Metrax 109086
overflow(p_res
, 1, rnd
, si
);
if((er
> -54) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)si
<< 63;
// some operands preclude setting NX for flushed subnormal
if(fp_zero
==type2
//DZ cancels NX
|| type2
>=fp_infinity
) exc
= 0;
exc
|= asm_fdivd(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_double(result
, &res
, STDONLY
, NULL
);
&& er
<= 0) //subnormal result?
if((er
> -54) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint64
)si
<< 63;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fsqrtd( const double* p_op2
, double* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fsqrtd(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fadds( const float* p_op1
, const float* p_op2
, float* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_single(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
&&(fp_subnormal
==type1
|| fp_subnormal
==type2
))
if(type1
>=fp_infinity
|| type2
>=fp_infinity
) exc
= 0;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fadds(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_single(result
, &res
, STDONLY
, NULL
);
if(stdmode
) return FPX_UN
;
//else gross underflow, zero result
res
.fp
.inte
= res
.sign
<< 31;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fsubs( const float* p_op1
, const float* p_op2
, float* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_single(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
&&(fp_subnormal
==type1
|| fp_subnormal
==type2
))
if(type1
>=fp_infinity
|| type2
>=fp_infinity
) exc
= 0;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fsubs(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_single(result
, &res
, STDONLY
, NULL
);
if(stdmode
) return FPX_UN
;
//else gross underflow, zero result
res
.fp
.inte
= res
.sign
<< 31;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fmuls( const float* p_op1
, const float* p_op2
, float* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int scr
[2], exc1
=0, exc2
=0;
int type1
= dissect_single(*p_op1
, &op1
, stdmode
, &exc1
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc2
);
int er
= op1
.exp
+ op2
.exp
- 127;
int si
= op1
.sign
^ op2
.sign
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
if((fp_subnormal
==type1
&& type2
<fp_infinity
&& type2
!=fp_zero
)
|| (fp_subnormal
==type2
&& type1
<fp_infinity
&& type1
!=fp_zero
))
if((er
> -25) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint
)si
<< 31;
// some operands preclude setting NX for flushed subnormal
|| (fp_zero
==type1
&& 0==exc1
) // either op exactly zero?
|| (fp_zero
==type2
&& 0==exc2
)) exc
= 0; // cancel NX
exc
|= asm_fmuls(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_single(result
, &res
, STDONLY
, NULL
);
&& er
<= 0) //subnormal result?
if((er
> -25) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint
)si
<< 31;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fsmuld( const float* p_op1
, const float* p_op2
, double* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int scr
[2], exc1
=0, exc2
=0;
int type1
= dissect_single(*p_op1
, &op1
, stdmode
, &exc1
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc2
);
if((fp_subnormal
==type1
&& type2
<fp_infinity
&& type2
!=fp_zero
)
|| (fp_subnormal
==type2
&& type1
<fp_infinity
&& type1
!=fp_zero
))
// some operands preclude setting NX for flushed subnormal
|| (fp_zero
==type1
&& 0==exc1
) // either op exactly zero?
|| (fp_zero
==type2
&& 0==exc2
)) exc
= 0; // cancel NX
exc
|= asm_fsmuld(&op1
.fp
.num
, &op2
.fp
.num
, p_res
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fdivs( const float* p_op1
, const float* p_op2
, float* p_res
,
uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type1
= dissect_single(*p_op1
, &op1
, stdmode
, &exc
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
int er
= op1
.exp
- op2
.exp
+ 127 - 1;
int si
= op1
.sign
^ op2
.sign
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
if((fp_subnormal
==type1
&& type2
<fp_infinity
&& type2
!=fp_zero
)
|| (fp_subnormal
==type2
&& type1
<fp_infinity
&& type1
!=fp_zero
))
if(fp_normal
== type1
) frac1
|= 0x800000;
if(fp_normal
== type2
) frac2
|= 0x800000;
if(ef
> 255) // **PRM error now frozen in HW** Metrax 109086
overflow(p_res
, 0, rnd
, si
);
if((er
> -25) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint
)si
<< 31;
// some operands preclude setting NX for flushed subnormal
if(fp_zero
==type2
//DZ cancels NX
|| type2
>=fp_infinity
) exc
= 0;
exc
|= asm_fdivs(&op1
.fp
.num
, &op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_single(result
, &res
, STDONLY
, NULL
);
&& er
<= 0) //subnormal result?
if((er
> -25) || (si
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint
)si
<< 31;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fsqrts( const float* p_op2
, float* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fsqrts(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fstod( const float* p_op2
, double* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
if(fp_subnormal
==type2
) return FPX_UN
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fstod(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fdtos( const double* p_op2
, float* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
int er
= op2
.exp
- 1023 + 127;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
if(op2
.sign
? (rnd
==FP_RM
) : (rnd
==FP_RP
)) return FPX_UN
;
//else gross underflow, zero result
res
.fp
.inte
= (uint
)op2
.sign
<< 31;
exc
|= asm_fdtos(&op2
.fp
.num
, &result
, rnd
, scr
);
int rtype
= dissect_single(result
, &res
, STDONLY
, NULL
);
&& er
<= 0) //subnormal result?
if((er
> -25) || (res
.sign
? (rnd
==FP_RM
) : (rnd
==FP_RP
)))
//else gross underflow, zero result
res
.fp
.inte
= (uint
)res
.sign
<< 31;
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fstox( const float* p_op2
, uint64
* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
if(fp_subnormal
==type2
) return FPX_UN
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fstox(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fdtox( const double* p_op2
, uint64
* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
if(fp_subnormal
==type2
) return FPX_UN
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fdtox(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fstoi( const float* p_op2
, uint
* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_single(*p_op2
, &op2
, stdmode
, &exc
);
if(fp_subnormal
==type2
) return FPX_UN
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fstoi(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fdtoi( const double* p_op2
, uint
* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int stdmode
= STDMODE(p_fsr
,p_gsr
);
int type2
= dissect_double(*p_op2
, &op2
, stdmode
, &exc
);
if(fp_subnormal
==type2
) return FPX_UN
;
int rnd
= RNDMODE(p_fsr
,p_gsr
);
exc
|= asm_fdtoi(&op2
.fp
.num
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fxtos( const uint64
* p_op2
, float* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int rnd
= RNDMODE(p_fsr
,p_gsr
);
int exc
= asm_fxtos(p_op2
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fxtod( const uint64
* p_op2
, double* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int rnd
= RNDMODE(p_fsr
,p_gsr
);
int exc
= asm_fxtod(p_op2
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fitos( const uint
* p_op2
, float* p_res
, uint64 p_fsr
, uint64 p_gsr
)
int rnd
= RNDMODE(p_fsr
,p_gsr
);
int exc
= asm_fitos(p_op2
, p_res
, rnd
, scr
);
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fpsim_fitod( const uint
* p_op2
, double* p_res
)
//-------------------------------------------------------------------
//-------------------------------------------------------------------
uint64
fpsim_gsr_mask(void) { return 0xFFFFFFFF0E0000FF; }
//-------------------------------------------------------------------
//-------------------------------------------------------------------
/* Merges a FP exception returned by one of the instruction sim routines
into the caller's FSR, and indicates whether the caller should
post a trap (nonzero return value is trap-type code).
fpsim_update_fsr( int p_exc
, uint64
* p_fsr
)
// non-IEEE trap? (unfinished or illegal)
trap
= p_exc
& 0xFF; // trap reason in bits 7:0
if(0x10 == trap
) return trap
; // illegal_instr: no fsr update
// FP_other trap: ftt in reason code
fsr
= (fsr
& ~0x1C000) | (trap
<< 14);
else // IEEE trap or completion
int taken
= p_exc
& (fsr
>>23) & 0x1F; // mask with fsr.tem
fsr
&= ~0x1C01F; // clear old fsr.cexc and fsr.ftt
// To Trap or Not To Trap?
if(taken
!= 0) // trap taken?
// cancel NX bit for OF/UF trap
if(taken
& (FPX_OF
|FPX_UF
))
fsr
|= (taken
| 0x04000); // set fsr.cexc only; fsr.ftt=1
trap
= 0x21; // IEEE_754_exception
// set both cexc,aexc identically
fsr
|= (p_exc
| (p_exc
<<5));
*p_fsr
= fsr
; // update caller's FSR
/*===========================================================================*/
/* Dissection routines: picks apart the FP number into sign,exp,fraction
and flushes subnormal numbers to zero in nonstandard mode.
Returns FP number class: 0=zero 1=subnorm 2=normal 3=inf 4=qnan 5=snan
dissect_double( double p_fpnum
, fpdouble
* p_data
, int p_std
, int* p_exc
)
p_data
->fp
.num
= p_fpnum
;
p_data
->sign
= p_data
->fp
.inte
>> 63;
p_data
->frac
= p_data
->fp
.inte
& 0x000FFFFFFFFFFFFF;
p_data
->exp
= (p_data
->fp
.inte
>> 52) & 0x7FF;
if(0 == p_data
->exp
) // exponent zero?
fpclass
= (0 == p_data
->frac
)
else if(0x7FF == p_data
->exp
) // exponent all ones?
if(0 == p_data
->frac
) fpclass
= fp_infinity
;
fpclass
= (p_data
->frac
& 0x0008000000000000) //frac.msb==1?
// nonstandard mode: flush subnormals to 0
&& fp_subnormal
== fpclass
)
p_data
->fp
.inte
= (uint64
)p_data
->sign
<< 63;
dissect_single( float p_fpnum
, fpsingle
* p_data
, int p_std
, int* p_exc
)
p_data
->fp
.num
= p_fpnum
;
p_data
->sign
= p_data
->fp
.inte
>> 31;
p_data
->frac
= p_data
->fp
.inte
& 0x007FFFFF;
p_data
->exp
= (p_data
->fp
.inte
>> 23) & 0xFF;
if(0 == p_data
->exp
) // exponent zero?
fpclass
= (0 == p_data
->frac
)
else if(0xFF == p_data
->exp
) // exponent all ones?
if(0 == p_data
->frac
) fpclass
= fp_infinity
;
fpclass
= (p_data
->frac
& 0x00400000) //frac.msb==1?
// nonstandard mode: flush subnormals to 0
&& fp_subnormal
== fpclass
)
p_data
->fp
.inte
= p_data
->sign
<< 31;
/*=======================================================================*/
/* overflow routine: returns proper result for overflow in rounding mode
overflow( void* p_res
, int p_dbl
, int p_rnd
, int p_sign
)
enum { MAXV
=0, INFV
=1 } rtype
; // result type: 1=infinity 0=max_value
switch(p_rnd
) //rounding mode?
case FP_RN
: rtype
= INFV
; break;
case FP_RZ
: rtype
= MAXV
; break;
case FP_RP
: rtype
= p_sign
? MAXV
: INFV
; break;
case FP_RM
: rtype
= p_sign
? INFV
: MAXV
; break;
uint64 d_res
= rtype
? 0x7FF0000000000000 : 0x7FEFFFFFFFFFFFFF;
*(uint64
*)p_res
= d_res
| ((uint64
)p_sign
<< 63);
uint s_res
= rtype
? 0x7F800000 : 0x7F7FFFFF;
*(uint
*)p_res
= s_res
| (p_sign
<< 31);
//-------------------------------------------------------------------
// un-implemented ops return illegal_instruction trap if called:
//-------------------------------------------------------------------
int fpsim_fnaddd(const double* a
,const double* b
,double* c
,uint64 d
,uint64 e
)
int fpsim_fnadds(const float* a
,const float* b
,float* c
,uint64 d
,uint64 e
)
int fpsim_fnmuld(const double* a
,const double* b
,double* c
,uint64 d
,uint64 e
)
int fpsim_fnmuls(const float* a
,const float* b
,float* c
,uint64 d
,uint64 e
)
int fpsim_fnsmuld(const float* a
,const float* b
,double* c
,uint64 d
,uint64 e
)
int fpsim_fhaddd(const double* a
,const double* b
,double* c
,uint64 d
,uint64 e
,
fpsim_fha_subtype f
) {return FPX_ILL
;}
int fpsim_fhadds(const float* a
,const float* b
,float* c
,uint64 d
,uint64 e
,
fpsim_fha_subtype f
) {return FPX_ILL
;}
int fpsim_fmaddd(const double* a
,const double* b
,const double* c
,double* d
,
uint64 e
,uint64 f
,fpsim_fma_subtype g
) {return FPX_ILL
;}
int fpsim_fmadds(const float* a
,const float* b
,const float* c
,float* d
,
uint64 e
,uint64 f
,fpsim_fma_subtype g
) {return FPX_ILL
;}
int fpsim_fumaddd(const double* a
,const double* b
,const double* c
,double* d
,
uint64 e
,uint64 f
,fpsim_fma_subtype g
) {return FPX_ILL
;}
int fpsim_fumadds(const float* a
,const float* b
,const float* c
,float* d
,
uint64 e
,uint64 f
,fpsim_fma_subtype g
) {return FPX_ILL
;}
/*===========================================================================*/
// Function pointer structure
struct fpsim_functions fpsim_funclist
=
fpsim_update_fsr
, fpsim_gsr_mask
,
fpsim_faddd
, fpsim_fsubd
, fpsim_fmuld
, fpsim_fdivd
, fpsim_fsqrtd
,
fpsim_fadds
, fpsim_fsubs
, fpsim_fmuls
, fpsim_fdivs
, fpsim_fsqrts
,
fpsim_fstod
, fpsim_fdtos
, fpsim_fstox
, fpsim_fdtox
, fpsim_fstoi
,
fpsim_fdtoi
, fpsim_fxtos
, fpsim_fxtod
, fpsim_fitos
, fpsim_fitod
,
fpsim_fnaddd
, fpsim_fnadds
, fpsim_fnmuld
, fpsim_fnmuls
, fpsim_fnsmuld
,
fpsim_fhaddd
, fpsim_fhadds
,
fpsim_fmaddd
, fpsim_fmadds
, fpsim_fumaddd
, fpsim_fumadds
char fpsim_fp_model
[] = "FPSIM Niagara2 (N2) " __DATE__
;