2005-04-16 15:20:36 -07:00
/*
* 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 01:49:14 +02:00
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-04-16 15:20:36 -07:00
*
* Nov 7 , 2000
* Modification to allow integration with Linux kernel
*
* Kevin D . Kissell , kevink @ mips . com and Carsten Langgard , carstenl @ mips . com
* Copyright ( C ) 2000 MIPS Technologies , Inc . All rights reserved .
2005-04-28 13:39:10 +00:00
*/
2005-10-23 13:44:31 +01:00
# ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
# define __ARCH_MIPS_MATH_EMU_IEEE754_H
2005-04-16 15:20:36 -07:00
2014-04-16 00:47:59 +02:00
# include <linux/compiler.h>
2005-04-28 13:39:10 +00:00
# include <asm/byteorder.h>
2014-04-19 14:20:54 +02:00
# include <linux/kernel.h>
2005-04-16 15:20:36 -07:00
# include <linux/types.h>
2005-04-28 13:39:10 +00:00
# include <linux/sched.h>
2014-04-16 00:40:02 +02:00
# include <asm/bitfield.h>
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754dp {
2005-04-16 15:20:36 -07:00
struct {
2014-04-16 00:40:02 +02:00
__BITFIELD_FIELD ( unsigned int sign : 1 ,
__BITFIELD_FIELD ( unsigned int bexp : 11 ,
__BITFIELD_FIELD ( u64 mant : 52 ,
; ) ) )
2014-04-25 15:48:40 +02:00
} ;
2005-04-16 15:20:36 -07:00
u64 bits ;
2014-04-16 01:31:11 +02:00
} ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754sp {
2014-04-25 15:48:40 +02:00
struct {
__BITFIELD_FIELD ( unsigned sign : 1 ,
__BITFIELD_FIELD ( unsigned bexp : 8 ,
__BITFIELD_FIELD ( unsigned mant : 23 ,
; ) ) )
} ;
2005-04-16 15:20:36 -07:00
u32 bits ;
2014-04-16 01:31:11 +02:00
} ;
2005-04-16 15:20:36 -07:00
/*
* single precision ( often aka float )
*/
2014-04-16 01:31:11 +02:00
int ieee754sp_class ( union ieee754sp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754sp ieee754sp_abs ( union ieee754sp x ) ;
union ieee754sp ieee754sp_neg ( union ieee754sp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754sp ieee754sp_add ( union ieee754sp x , union ieee754sp y ) ;
union ieee754sp ieee754sp_sub ( union ieee754sp x , union ieee754sp y ) ;
union ieee754sp ieee754sp_mul ( union ieee754sp x , union ieee754sp y ) ;
union ieee754sp ieee754sp_div ( union ieee754sp x , union ieee754sp y ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754sp ieee754sp_fint ( int x ) ;
union ieee754sp ieee754sp_flong ( s64 x ) ;
union ieee754sp ieee754sp_fdp ( union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
int ieee754sp_tint ( union ieee754sp x ) ;
s64 ieee754sp_tlong ( union ieee754sp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
int ieee754sp_cmp ( union ieee754sp x , union ieee754sp y , int cop , int sig ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754sp ieee754sp_sqrt ( union ieee754sp x ) ;
2005-04-16 15:20:36 -07:00
2015-08-13 09:56:31 +02:00
union ieee754sp ieee754sp_maddf ( union ieee754sp z , union ieee754sp x ,
union ieee754sp y ) ;
2015-08-13 09:56:32 +02:00
union ieee754sp ieee754sp_msubf ( union ieee754sp z , union ieee754sp x ,
union ieee754sp y ) ;
2015-08-13 09:56:34 +02:00
int ieee754sp_2008class ( union ieee754sp x ) ;
2015-08-13 09:56:35 +02:00
union ieee754sp ieee754sp_fmin ( union ieee754sp x , union ieee754sp y ) ;
union ieee754sp ieee754sp_fmina ( union ieee754sp x , union ieee754sp y ) ;
2015-08-13 09:56:36 +02:00
union ieee754sp ieee754sp_fmax ( union ieee754sp x , union ieee754sp y ) ;
union ieee754sp ieee754sp_fmaxa ( union ieee754sp x , union ieee754sp y ) ;
2015-08-13 09:56:31 +02:00
2005-04-16 15:20:36 -07:00
/*
* double precision ( often aka double )
*/
2014-04-16 01:31:11 +02:00
int ieee754dp_class ( union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754dp ieee754dp_add ( union ieee754dp x , union ieee754dp y ) ;
union ieee754dp ieee754dp_sub ( union ieee754dp x , union ieee754dp y ) ;
union ieee754dp ieee754dp_mul ( union ieee754dp x , union ieee754dp y ) ;
union ieee754dp ieee754dp_div ( union ieee754dp x , union ieee754dp y ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754dp ieee754dp_abs ( union ieee754dp x ) ;
union ieee754dp ieee754dp_neg ( union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754dp ieee754dp_fint ( int x ) ;
union ieee754dp ieee754dp_flong ( s64 x ) ;
union ieee754dp ieee754dp_fsp ( union ieee754sp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
int ieee754dp_tint ( union ieee754dp x ) ;
s64 ieee754dp_tlong ( union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
int ieee754dp_cmp ( union ieee754dp x , union ieee754dp y , int cop , int sig ) ;
2005-04-16 15:20:36 -07:00
2014-04-16 01:31:11 +02:00
union ieee754dp ieee754dp_sqrt ( union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2015-08-13 09:56:31 +02:00
union ieee754dp ieee754dp_maddf ( union ieee754dp z , union ieee754dp x ,
union ieee754dp y ) ;
2015-08-13 09:56:32 +02:00
union ieee754dp ieee754dp_msubf ( union ieee754dp z , union ieee754dp x ,
union ieee754dp y ) ;
2015-08-13 09:56:34 +02:00
int ieee754dp_2008class ( union ieee754dp x ) ;
2015-08-13 09:56:35 +02:00
union ieee754dp ieee754dp_fmin ( union ieee754dp x , union ieee754dp y ) ;
union ieee754dp ieee754dp_fmina ( union ieee754dp x , union ieee754dp y ) ;
2015-08-13 09:56:36 +02:00
union ieee754dp ieee754dp_fmax ( union ieee754dp x , union ieee754dp y ) ;
union ieee754dp ieee754dp_fmaxa ( union ieee754dp x , union ieee754dp y ) ;
2005-04-16 15:20:36 -07:00
/* 5 types of floating point number
*/
2014-04-19 00:36:32 +02:00
enum {
IEEE754_CLASS_NORM = 0x00 ,
IEEE754_CLASS_ZERO = 0x01 ,
IEEE754_CLASS_DNORM = 0x02 ,
IEEE754_CLASS_INF = 0x03 ,
IEEE754_CLASS_SNAN = 0x04 ,
IEEE754_CLASS_QNAN = 0x05 ,
} ;
2005-04-16 15:20:36 -07:00
/* exception numbers */
# define IEEE754_INEXACT 0x01
# define IEEE754_UNDERFLOW 0x02
# define IEEE754_OVERFLOW 0x04
# define IEEE754_ZERO_DIVIDE 0x08
# define IEEE754_INVALID_OPERATION 0x10
/* cmp operators
*/
# define IEEE754_CLT 0x01
# define IEEE754_CEQ 0x02
# define IEEE754_CGT 0x04
# define IEEE754_CUN 0x08
2005-04-28 13:39:10 +00:00
/*
* The control status register
*/
struct _ieee754_csr {
2015-04-03 23:27:38 +01:00
__BITFIELD_FIELD ( unsigned fcc : 7 , /* condition[7:1] */
__BITFIELD_FIELD ( unsigned nod : 1 , /* set 1 for no denormals */
__BITFIELD_FIELD ( unsigned c : 1 , /* condition[0] */
__BITFIELD_FIELD ( unsigned pad0 : 3 ,
__BITFIELD_FIELD ( unsigned abs2008 : 1 , /* IEEE 754-2008 ABS/NEG.fmt */
__BITFIELD_FIELD ( unsigned nan2008 : 1 , /* IEEE 754-2008 NaN mode */
2014-04-16 00:40:02 +02:00
__BITFIELD_FIELD ( unsigned cx : 6 , /* exceptions this operation */
__BITFIELD_FIELD ( unsigned mx : 5 , /* exception enable mask */
__BITFIELD_FIELD ( unsigned sx : 5 , /* exceptions total */
__BITFIELD_FIELD ( unsigned rm : 2 , /* current rounding mode */
2015-04-03 23:27:38 +01:00
; ) ) ) ) ) ) ) ) ) )
2005-04-16 15:20:36 -07:00
} ;
2006-05-16 01:26:03 +09:00
# define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31))
2005-04-16 15:20:36 -07:00
2005-04-28 13:39:10 +00:00
static inline unsigned ieee754_getrm ( void )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . rm ) ;
}
2005-04-28 13:39:10 +00:00
static inline unsigned ieee754_setrm ( unsigned rm )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . rm = rm ) ;
}
/*
* get current exceptions
*/
2005-04-28 13:39:10 +00:00
static inline unsigned ieee754_getcx ( void )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . cx ) ;
}
/* test for current exception condition
*/
2005-04-28 13:39:10 +00:00
static inline int ieee754_cxtest ( unsigned n )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . cx & n ) ;
}
/*
* get sticky exceptions
*/
2005-04-28 13:39:10 +00:00
static inline unsigned ieee754_getsx ( void )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . sx ) ;
}
/* clear sticky conditions
*/
2005-04-28 13:39:10 +00:00
static inline unsigned ieee754_clrsx ( void )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . sx = 0 ) ;
}
/* test for sticky exception condition
*/
2005-04-28 13:39:10 +00:00
static inline int ieee754_sxtest ( unsigned n )
2005-04-16 15:20:36 -07:00
{
return ( ieee754_csr . sx & n ) ;
}
/* debugging */
2014-04-16 01:31:11 +02:00
union ieee754sp ieee754sp_dump ( char * s , union ieee754sp x ) ;
union ieee754dp ieee754dp_dump ( char * s , union ieee754dp x ) ;
2005-04-16 15:20:36 -07:00
2015-04-03 23:24:09 +01:00
# define IEEE754_SPCVAL_PZERO 0 /* +0.0 */
# define IEEE754_SPCVAL_NZERO 1 /* -0.0 */
# define IEEE754_SPCVAL_PONE 2 /* +1.0 */
# define IEEE754_SPCVAL_NONE 3 /* -1.0 */
# define IEEE754_SPCVAL_PTEN 4 /* +10.0 */
# define IEEE754_SPCVAL_NTEN 5 /* -10.0 */
# define IEEE754_SPCVAL_PINFINITY 6 /* +inf */
# define IEEE754_SPCVAL_NINFINITY 7 /* -inf */
2015-11-13 00:47:28 +00:00
# define IEEE754_SPCVAL_INDEF_LEG 8 /* legacy quiet NaN */
# define IEEE754_SPCVAL_INDEF_2008 9 /* IEEE 754-2008 quiet NaN */
# define IEEE754_SPCVAL_PMAX 10 /* +max norm */
# define IEEE754_SPCVAL_NMAX 11 /* -max norm */
# define IEEE754_SPCVAL_PMIN 12 /* +min norm */
# define IEEE754_SPCVAL_NMIN 13 /* -min norm */
# define IEEE754_SPCVAL_PMIND 14 /* +min denorm */
# define IEEE754_SPCVAL_NMIND 15 /* -min denorm */
# define IEEE754_SPCVAL_P1E31 16 /* + 1.0e31 */
# define IEEE754_SPCVAL_P1E63 17 /* + 1.0e63 */
2005-04-16 15:20:36 -07:00
2014-04-25 15:48:40 +02:00
extern const union ieee754dp __ieee754dp_spcvals [ ] ;
extern const union ieee754sp __ieee754sp_spcvals [ ] ;
2014-04-16 01:31:11 +02:00
# define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals)
# define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals)
2005-04-16 15:20:36 -07:00
2005-04-28 13:39:10 +00:00
/*
* Return infinity with given sign
*/
# define ieee754dp_inf(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
# define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
# define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
# define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
2015-11-13 00:47:28 +00:00
# define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \
ieee754_csr . nan2008 ] )
2005-04-28 13:39:10 +00:00
# define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
# define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
# define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
# define ieee754dp_1e31() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
# define ieee754dp_1e63() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
# define ieee754sp_inf(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
# define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
# define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
# define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
2015-11-13 00:47:28 +00:00
# define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \
ieee754_csr . nan2008 ] )
2005-04-28 13:39:10 +00:00
# define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
# define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
# define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
# define ieee754sp_1e31() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
# define ieee754sp_1e63() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
/*
* Indefinite integer value
*/
2014-04-19 14:20:54 +02:00
static inline int ieee754si_indef ( void )
{
2015-11-13 00:47:28 +00:00
return ieee754_csr . nan2008 ? 0 : INT_MAX ;
2014-04-19 14:20:54 +02:00
}
static inline s64 ieee754di_indef ( void )
{
2015-11-13 00:47:28 +00:00
return ieee754_csr . nan2008 ? 0 : S64_MAX ;
}
/*
* Overflow integer value
*/
static inline int ieee754si_overflow ( int xs )
{
return ieee754_csr . nan2008 & & xs ? INT_MIN : INT_MAX ;
}
static inline s64 ieee754di_overflow ( int xs )
{
return ieee754_csr . nan2008 & & xs ? S64_MIN : S64_MAX ;
2014-04-19 14:20:54 +02:00
}
2005-04-16 15:20:36 -07:00
/* result types for xctx.rt */
# define IEEE754_RT_SP 0
# define IEEE754_RT_DP 1
# define IEEE754_RT_XP 2
# define IEEE754_RT_SI 3
# define IEEE754_RT_DI 4
/* compat */
# define ieee754dp_fix(x) ieee754dp_tint(x)
# define ieee754sp_fix(x) ieee754sp_tint(x)
2005-10-23 13:44:31 +01:00
# endif /* __ARCH_MIPS_MATH_EMU_IEEE754_H */