Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Этот коммит содержится в:
19
arch/parisc/math-emu/Makefile
Обычный файл
19
arch/parisc/math-emu/Makefile
Обычный файл
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Makefile for the linux/parisc floating point code
|
||||
#
|
||||
|
||||
# See arch/parisc/math-emu/README
|
||||
CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
|
||||
-Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
|
||||
-Wno-implicit-int
|
||||
|
||||
obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
|
||||
dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \
|
||||
sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \
|
||||
fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \
|
||||
dfrem.o sfrem.o dfcmp.o sfcmp.o
|
||||
|
||||
# Math emulation code beyond the FRND is required for 712/80i and
|
||||
# other very old or stripped-down PA-RISC CPUs -- not currently supported
|
||||
|
||||
obj-$(CONFIG_MATH_EMULATION) += unimplemented-math-emulation.o
|
11
arch/parisc/math-emu/README
Обычный файл
11
arch/parisc/math-emu/README
Обычный файл
@@ -0,0 +1,11 @@
|
||||
All files except driver.c are snapshots from the HP-UX kernel. They've
|
||||
been modified as little as possible. Even though they don't fit the
|
||||
Linux coding style, please leave them in their funny format just in case
|
||||
someone in the future, with access to HP-UX source code, is generous
|
||||
enough to update our copies with later changes from HP-UX -- it'll
|
||||
make their 'diff' job easier if our code is relatively unmodified.
|
||||
|
||||
Required Disclaimer: Hewlett-Packard makes no implied or expressed
|
||||
warranties about this code nor any promises to maintain or test it
|
||||
in any way. This copy of this snapshot is no longer the property
|
||||
of Hewlett-Packard.
|
377
arch/parisc/math-emu/cnv_float.h
Обычный файл
377
arch/parisc/math-emu/cnv_float.h
Обычный файл
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some more constants
|
||||
*/
|
||||
#define SGL_FX_MAX_EXP 30
|
||||
#define DBL_FX_MAX_EXP 62
|
||||
#define QUAD_FX_MAX_EXP 126
|
||||
|
||||
#define Dintp1(object) (object)
|
||||
#define Dintp2(object) (object)
|
||||
|
||||
#define Duintp1(object) (object)
|
||||
#define Duintp2(object) (object)
|
||||
|
||||
#define Qintp0(object) (object)
|
||||
#define Qintp1(object) (object)
|
||||
#define Qintp2(object) (object)
|
||||
#define Qintp3(object) (object)
|
||||
|
||||
|
||||
/*
|
||||
* These macros will be used specifically by the convert instructions.
|
||||
*
|
||||
*
|
||||
* Single format macros
|
||||
*/
|
||||
|
||||
#define Sgl_to_dbl_exponent(src_exponent,dest) \
|
||||
Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS))
|
||||
|
||||
#define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \
|
||||
Deposit_dmantissap1(destA,src_mantissa>>3); \
|
||||
Dmantissap2(destB) = src_mantissa << 29
|
||||
|
||||
#define Sgl_isinexact_to_fix(sgl_value,exponent) \
|
||||
((exponent < (SGL_P - 1)) ? \
|
||||
(Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE)
|
||||
|
||||
#define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH)
|
||||
|
||||
#define Sgl_roundnearest_from_int(int_value,sgl_value) \
|
||||
if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \
|
||||
if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
|
||||
Sall(sgl_value)++
|
||||
|
||||
#define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \
|
||||
((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB))
|
||||
|
||||
#define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \
|
||||
if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \
|
||||
if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \
|
||||
Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
|
||||
|
||||
#define Dint_isinexact_to_dbl(dint_value) \
|
||||
(Dintp2(dint_value) << 33 - DBL_EXP_LENGTH)
|
||||
|
||||
#define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \
|
||||
if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \
|
||||
if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
|
||||
if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
|
||||
|
||||
#define Sgl_isone_roundbit(sgl_value,exponent) \
|
||||
((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31)
|
||||
|
||||
#define Sgl_isone_stickybit(sgl_value,exponent) \
|
||||
(exponent < (SGL_P - 2) ? \
|
||||
Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE)
|
||||
|
||||
|
||||
/*
|
||||
* Double format macros
|
||||
*/
|
||||
|
||||
#define Dbl_to_sgl_exponent(src_exponent,dest) \
|
||||
dest = src_exponent + (SGL_BIAS - DBL_BIAS)
|
||||
|
||||
#define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \
|
||||
Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
|
||||
guard = Dbit3p2(srcB); \
|
||||
sticky = Dallp2(srcB)<<4; \
|
||||
inexact = guard | sticky; \
|
||||
odd = Dbit2p2(srcB)
|
||||
|
||||
#define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \
|
||||
Deposit_dexponent(srcA,1); \
|
||||
tiny = TRUE; \
|
||||
if (exp >= -2) { \
|
||||
if (exp == 0) { \
|
||||
inexact = Dallp2(srcB) << 3; \
|
||||
guard = inexact >> 31; \
|
||||
sticky = inexact << 1; \
|
||||
Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \
|
||||
odd = dest << 31; \
|
||||
if (inexact) { \
|
||||
switch(Rounding_mode()) { \
|
||||
case ROUNDPLUS: \
|
||||
if (Dbl_iszero_sign(srcA)) { \
|
||||
dest++; \
|
||||
if (Sgl_isone_hidden(dest)) \
|
||||
tiny = FALSE; \
|
||||
dest--; \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDMINUS: \
|
||||
if (Dbl_isone_sign(srcA)) { \
|
||||
dest++; \
|
||||
if (Sgl_isone_hidden(dest)) \
|
||||
tiny = FALSE; \
|
||||
dest--; \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDNEAREST: \
|
||||
if (guard && (sticky || odd)) { \
|
||||
dest++; \
|
||||
if (Sgl_isone_hidden(dest)) \
|
||||
tiny = FALSE; \
|
||||
dest--; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
/* shift right by one to get correct result */ \
|
||||
guard = odd; \
|
||||
sticky = inexact; \
|
||||
inexact |= guard; \
|
||||
dest >>= 1; \
|
||||
Deposit_dsign(srcA,0); \
|
||||
Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \
|
||||
odd = dest << 31; \
|
||||
} \
|
||||
else { \
|
||||
inexact = Dallp2(srcB) << (2 + exp); \
|
||||
guard = inexact >> 31; \
|
||||
sticky = inexact << 1; \
|
||||
Deposit_dsign(srcA,0); \
|
||||
if (exp == -2) dest = Dallp1(srcA); \
|
||||
else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \
|
||||
odd = dest << 31; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
Deposit_dsign(srcA,0); \
|
||||
if (exp > (1 - SGL_P)) { \
|
||||
dest = Dallp1(srcA) >> (- 2 - exp); \
|
||||
inexact = Dallp1(srcA) << (34 + exp); \
|
||||
guard = inexact >> 31; \
|
||||
sticky = (inexact << 1) | Dallp2(srcB); \
|
||||
inexact |= Dallp2(srcB); \
|
||||
odd = dest << 31; \
|
||||
} \
|
||||
else { \
|
||||
dest = 0; \
|
||||
inexact = Dallp1(srcA) | Dallp2(srcB); \
|
||||
if (exp == (1 - SGL_P)) { \
|
||||
guard = Dhidden(srcA); \
|
||||
sticky = Dmantissap1(srcA) | Dallp2(srcB); \
|
||||
} \
|
||||
else { \
|
||||
guard = 0; \
|
||||
sticky = inexact; \
|
||||
} \
|
||||
odd = 0; \
|
||||
} \
|
||||
} \
|
||||
exp = 0
|
||||
|
||||
#define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \
|
||||
(exponent < (DBL_P-33) ? \
|
||||
Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \
|
||||
(exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \
|
||||
FALSE))
|
||||
|
||||
#define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \
|
||||
((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \
|
||||
Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 )
|
||||
|
||||
#define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \
|
||||
((exponent < (DBL_P - 33) ? \
|
||||
Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \
|
||||
Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1)
|
||||
|
||||
#define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \
|
||||
(exponent < (DBL_P-34) ? \
|
||||
(Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \
|
||||
(exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \
|
||||
FALSE))
|
||||
|
||||
|
||||
/* Int macros */
|
||||
|
||||
#define Int_from_sgl_mantissa(sgl_value,exponent) \
|
||||
Sall(sgl_value) = \
|
||||
(unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent)
|
||||
|
||||
#define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \
|
||||
if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \
|
||||
else Dallp1(dbl_valueA) <<= 1
|
||||
|
||||
#define Int_negate(int_value) int_value = -int_value
|
||||
|
||||
|
||||
/* Dint macros */
|
||||
|
||||
#define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
|
||||
{Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
|
||||
if (exponent <= 31) { \
|
||||
Dintp1(dresultA) = 0; \
|
||||
Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
|
||||
} \
|
||||
else { \
|
||||
Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
|
||||
Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
|
||||
}}
|
||||
|
||||
|
||||
#define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
|
||||
{if (exponent < 32) { \
|
||||
Dintp1(destA) = 0; \
|
||||
if (exponent <= 20) \
|
||||
Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \
|
||||
else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
|
||||
52-exponent,Dintp2(destB)); \
|
||||
} \
|
||||
else { \
|
||||
if (exponent <= 52) { \
|
||||
Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \
|
||||
if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \
|
||||
else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
|
||||
52-exponent,Dintp2(destB)); \
|
||||
} \
|
||||
else { \
|
||||
Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
|
||||
84-exponent,Dintp1(destA)); \
|
||||
Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define Dint_setzero(dresultA,dresultB) \
|
||||
Dintp1(dresultA) = 0; \
|
||||
Dintp2(dresultB) = 0
|
||||
|
||||
#define Dint_setone_sign(dresultA,dresultB) \
|
||||
Dintp1(dresultA) = ~Dintp1(dresultA); \
|
||||
if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++
|
||||
|
||||
#define Dint_set_minint(dresultA,dresultB) \
|
||||
Dintp1(dresultA) = (unsigned int)1<<31; \
|
||||
Dintp2(dresultB) = 0
|
||||
|
||||
#define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01)
|
||||
|
||||
#define Dint_increment(dresultA,dresultB) \
|
||||
if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++
|
||||
|
||||
#define Dint_decrement(dresultA,dresultB) \
|
||||
if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)--
|
||||
|
||||
#define Dint_negate(dresultA,dresultB) \
|
||||
Dintp1(dresultA) = ~Dintp1(dresultA); \
|
||||
if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++
|
||||
|
||||
#define Dint_copyfromptr(src,destA,destB) \
|
||||
Dintp1(destA) = src->wd0; \
|
||||
Dintp2(destB) = src->wd1
|
||||
#define Dint_copytoptr(srcA,srcB,dest) \
|
||||
dest->wd0 = Dintp1(srcA); \
|
||||
dest->wd1 = Dintp2(srcB)
|
||||
|
||||
|
||||
/* other macros */
|
||||
|
||||
#define Find_ms_one_bit(value, position) \
|
||||
{ \
|
||||
int var; \
|
||||
for (var=8; var >=1; var >>= 1) { \
|
||||
if (value >> 32 - position) \
|
||||
position -= var; \
|
||||
else position += var; \
|
||||
} \
|
||||
if ((value >> 32 - position) == 0) \
|
||||
position--; \
|
||||
else position -= 2; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unsigned int macros
|
||||
*/
|
||||
#define Duint_copyfromptr(src,destA,destB) \
|
||||
Dint_copyfromptr(src,destA,destB)
|
||||
#define Duint_copytoptr(srcA,srcB,dest) \
|
||||
Dint_copytoptr(srcA,srcB,dest)
|
||||
|
||||
#define Suint_isinexact_to_sgl(int_value) \
|
||||
(int_value << 32 - SGL_EXP_LENGTH)
|
||||
|
||||
#define Sgl_roundnearest_from_suint(suint_value,sgl_value) \
|
||||
if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \
|
||||
if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \
|
||||
Sall(sgl_value)++
|
||||
|
||||
#define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \
|
||||
((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB))
|
||||
|
||||
#define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \
|
||||
if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \
|
||||
if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \
|
||||
Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
|
||||
|
||||
#define Duint_isinexact_to_dbl(duint_value) \
|
||||
(Duintp2(duint_value) << 32 - DBL_EXP_LENGTH)
|
||||
|
||||
#define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \
|
||||
if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \
|
||||
if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
|
||||
if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
|
||||
|
||||
#define Suint_from_sgl_mantissa(src,exponent,result) \
|
||||
Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent)
|
||||
|
||||
#define Sgl_isinexact_to_unsigned(sgl_value,exponent) \
|
||||
Sgl_isinexact_to_fix(sgl_value,exponent)
|
||||
|
||||
#define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \
|
||||
{Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \
|
||||
if (exponent <= 31) { \
|
||||
Dintp1(dresultA) = 0; \
|
||||
Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
|
||||
} \
|
||||
else { \
|
||||
Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \
|
||||
Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \
|
||||
} \
|
||||
Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \
|
||||
}
|
||||
|
||||
#define Duint_setzero(dresultA,dresultB) \
|
||||
Dint_setzero(dresultA,dresultB)
|
||||
|
||||
#define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB)
|
||||
|
||||
#define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB)
|
||||
|
||||
#define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \
|
||||
Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \
|
||||
dest = (unsigned)dest >> 31 - exponent
|
||||
|
||||
#define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \
|
||||
Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)
|
||||
|
||||
#define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
|
||||
Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB)
|
847
arch/parisc/math-emu/dbl_float.h
Обычный файл
847
arch/parisc/math-emu/dbl_float.h
Обычный файл
@@ -0,0 +1,847 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
/* 32-bit word grabing functions */
|
||||
#define Dbl_firstword(value) Dallp1(value)
|
||||
#define Dbl_secondword(value) Dallp2(value)
|
||||
#define Dbl_thirdword(value) dummy_location
|
||||
#define Dbl_fourthword(value) dummy_location
|
||||
|
||||
#define Dbl_sign(object) Dsign(object)
|
||||
#define Dbl_exponent(object) Dexponent(object)
|
||||
#define Dbl_signexponent(object) Dsignexponent(object)
|
||||
#define Dbl_mantissap1(object) Dmantissap1(object)
|
||||
#define Dbl_mantissap2(object) Dmantissap2(object)
|
||||
#define Dbl_exponentmantissap1(object) Dexponentmantissap1(object)
|
||||
#define Dbl_allp1(object) Dallp1(object)
|
||||
#define Dbl_allp2(object) Dallp2(object)
|
||||
|
||||
/* dbl_and_signs ands the sign bits of each argument and puts the result
|
||||
* into the first argument. dbl_or_signs ors those same sign bits */
|
||||
#define Dbl_and_signs( src1dst, src2) \
|
||||
Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
|
||||
#define Dbl_or_signs( src1dst, src2) \
|
||||
Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst)
|
||||
|
||||
/* The hidden bit is always the low bit of the exponent */
|
||||
#define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1)
|
||||
#define Dbl_clear_signexponent_set_hidden(srcdst) \
|
||||
Deposit_dsignexponent(srcdst,1)
|
||||
#define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31)
|
||||
#define Dbl_clear_signexponent(srcdst) \
|
||||
Dallp1(srcdst) &= Dmantissap1((unsigned int)-1)
|
||||
|
||||
/* Exponent field for doubles has already been cleared and may be
|
||||
* included in the shift. Here we need to generate two double width
|
||||
* variable shifts. The insignificant bits can be ignored.
|
||||
* MTSAR f(varamount)
|
||||
* VSHD srcdst.high,srcdst.low => srcdst.low
|
||||
* VSHD 0,srcdst.high => srcdst.high
|
||||
* This is very difficult to model with C expressions since the shift amount
|
||||
* could exceed 32. */
|
||||
/* varamount must be less than 64 */
|
||||
#define Dbl_rightshift(srcdstA, srcdstB, varamount) \
|
||||
{if((varamount) >= 32) { \
|
||||
Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \
|
||||
Dallp1(srcdstA)=0; \
|
||||
} \
|
||||
else if(varamount > 0) { \
|
||||
Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \
|
||||
(varamount), Dallp2(srcdstB)); \
|
||||
Dallp1(srcdstA) >>= varamount; \
|
||||
} }
|
||||
/* varamount must be less than 64 */
|
||||
#define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \
|
||||
{if((varamount) >= 32) { \
|
||||
Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \
|
||||
Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \
|
||||
} \
|
||||
else if(varamount > 0) { \
|
||||
Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \
|
||||
(varamount), Dallp2(srcdstB)); \
|
||||
Deposit_dexponentmantissap1(srcdstA, \
|
||||
(Dexponentmantissap1(srcdstA)>>varamount)); \
|
||||
} }
|
||||
/* varamount must be less than 64 */
|
||||
#define Dbl_leftshift(srcdstA, srcdstB, varamount) \
|
||||
{if((varamount) >= 32) { \
|
||||
Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \
|
||||
Dallp2(srcdstB)=0; \
|
||||
} \
|
||||
else { \
|
||||
if ((varamount) > 0) { \
|
||||
Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \
|
||||
(Dallp2(srcdstB) >> (32-(varamount))); \
|
||||
Dallp2(srcdstB) <<= varamount; \
|
||||
} \
|
||||
} }
|
||||
#define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \
|
||||
Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \
|
||||
Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb))
|
||||
|
||||
#define Dbl_rightshiftby1_withextent(leftb,right,dst) \
|
||||
Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \
|
||||
Extlow(right)
|
||||
|
||||
#define Dbl_arithrightshiftby1(srcdstA,srcdstB) \
|
||||
Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\
|
||||
Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1
|
||||
|
||||
/* Sign extend the sign bit with an integer destination */
|
||||
#define Dbl_signextendedsign(value) Dsignedsign(value)
|
||||
|
||||
#define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0)
|
||||
/* Singles and doubles may include the sign and exponent fields. The
|
||||
* hidden bit and the hidden overflow must be included. */
|
||||
#define Dbl_increment(dbl_valueA,dbl_valueB) \
|
||||
if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1
|
||||
#define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \
|
||||
if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \
|
||||
Deposit_dmantissap1(dbl_valueA,dbl_valueA+1)
|
||||
#define Dbl_decrement(dbl_valueA,dbl_valueB) \
|
||||
if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \
|
||||
Dallp2(dbl_valueB) -= 1
|
||||
|
||||
#define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0)
|
||||
#define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0)
|
||||
#define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0)
|
||||
#define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0)
|
||||
#define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0)
|
||||
#define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff)
|
||||
#define Dbl_isnotzero(dbl_valueA,dbl_valueB) \
|
||||
(Dallp1(dbl_valueA) || Dallp2(dbl_valueB))
|
||||
#define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \
|
||||
(Dhiddenhigh7mantissa(dbl_value)!=0)
|
||||
#define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0)
|
||||
#define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \
|
||||
(Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
|
||||
#define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0)
|
||||
#define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0)
|
||||
#define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \
|
||||
(Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
|
||||
#define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0)
|
||||
#define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \
|
||||
Dallp2(dbl_valueB)==0)
|
||||
#define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0)
|
||||
#define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0)
|
||||
#define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0)
|
||||
#define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0)
|
||||
#define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \
|
||||
(Dhiddenhigh3mantissa(dbl_value)==0)
|
||||
#define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \
|
||||
(Dhiddenhigh7mantissa(dbl_value)==0)
|
||||
#define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0)
|
||||
#define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0)
|
||||
#define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \
|
||||
(Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
|
||||
#define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \
|
||||
(Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
|
||||
#define Dbl_isinfinity_exponent(dbl_value) \
|
||||
(Dexponent(dbl_value)==DBL_INFINITY_EXPONENT)
|
||||
#define Dbl_isnotinfinity_exponent(dbl_value) \
|
||||
(Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT)
|
||||
#define Dbl_isinfinity(dbl_valueA,dbl_valueB) \
|
||||
(Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
|
||||
Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
|
||||
#define Dbl_isnan(dbl_valueA,dbl_valueB) \
|
||||
(Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \
|
||||
(Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0))
|
||||
#define Dbl_isnotnan(dbl_valueA,dbl_valueB) \
|
||||
(Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \
|
||||
(Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0))
|
||||
|
||||
#define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
|
||||
(Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
|
||||
(Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
|
||||
Dallp2(dbl_op1b) < Dallp2(dbl_op2b)))
|
||||
#define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
|
||||
(Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
|
||||
(Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
|
||||
Dallp2(dbl_op1b) > Dallp2(dbl_op2b)))
|
||||
#define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
|
||||
(Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \
|
||||
(Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
|
||||
Dallp2(dbl_op1b) >= Dallp2(dbl_op2b)))
|
||||
#define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
|
||||
(Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \
|
||||
(Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \
|
||||
Dallp2(dbl_op1b) <= Dallp2(dbl_op2b)))
|
||||
#define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
|
||||
((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \
|
||||
(Dallp2(dbl_op1b) == Dallp2(dbl_op2b)))
|
||||
|
||||
#define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 8
|
||||
#define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 7
|
||||
#define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 4
|
||||
#define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 3
|
||||
#define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 2
|
||||
#define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \
|
||||
Dallp2(dbl_valueB) <<= 1
|
||||
|
||||
#define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \
|
||||
Dallp1(dbl_valueA) >>= 8
|
||||
#define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \
|
||||
Dallp1(dbl_valueA) >>= 4
|
||||
#define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \
|
||||
Dallp1(dbl_valueA) >>= 2
|
||||
#define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \
|
||||
Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \
|
||||
Dallp1(dbl_valueA) >>= 1
|
||||
|
||||
/* This magnitude comparison uses the signless first words and
|
||||
* the regular part2 words. The comparison is graphically:
|
||||
*
|
||||
* 1st greater? -------------
|
||||
* |
|
||||
* 1st less?-----------------+---------
|
||||
* | |
|
||||
* 2nd greater or equal----->| |
|
||||
* False True
|
||||
*/
|
||||
#define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
|
||||
((signlessleft <= signlessright) && \
|
||||
( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) ))
|
||||
|
||||
#define Dbl_copytoint_exponentmantissap1(src,dest) \
|
||||
dest = Dexponentmantissap1(src)
|
||||
|
||||
/* A quiet NaN has the high mantissa bit clear and at least on other (in this
|
||||
* case the adjacent bit) bit set. */
|
||||
#define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1)
|
||||
#define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp)
|
||||
|
||||
#define Dbl_set_mantissa(desta,destb,valuea,valueb) \
|
||||
Deposit_dmantissap1(desta,valuea); \
|
||||
Dmantissap2(destb) = Dmantissap2(valueb)
|
||||
#define Dbl_set_mantissap1(desta,valuea) \
|
||||
Deposit_dmantissap1(desta,valuea)
|
||||
#define Dbl_set_mantissap2(destb,valueb) \
|
||||
Dmantissap2(destb) = Dmantissap2(valueb)
|
||||
|
||||
#define Dbl_set_exponentmantissa(desta,destb,valuea,valueb) \
|
||||
Deposit_dexponentmantissap1(desta,valuea); \
|
||||
Dmantissap2(destb) = Dmantissap2(valueb)
|
||||
#define Dbl_set_exponentmantissap1(dest,value) \
|
||||
Deposit_dexponentmantissap1(dest,value)
|
||||
|
||||
#define Dbl_copyfromptr(src,desta,destb) \
|
||||
Dallp1(desta) = src->wd0; \
|
||||
Dallp2(destb) = src->wd1
|
||||
#define Dbl_copytoptr(srca,srcb,dest) \
|
||||
dest->wd0 = Dallp1(srca); \
|
||||
dest->wd1 = Dallp2(srcb)
|
||||
|
||||
/* An infinity is represented with the max exponent and a zero mantissa */
|
||||
#define Dbl_setinfinity_exponent(dbl_value) \
|
||||
Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT)
|
||||
#define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \
|
||||
Deposit_dexponentmantissap1(dbl_valueA, \
|
||||
(DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \
|
||||
Dmantissap2(dbl_valueB) = 0
|
||||
#define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) \
|
||||
= (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
|
||||
Dmantissap2(dbl_valueB) = 0
|
||||
#define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \
|
||||
(DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
|
||||
Dmantissap2(dbl_valueB) = 0
|
||||
#define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \
|
||||
Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
|
||||
(DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \
|
||||
Dmantissap2(dbl_valueB) = 0
|
||||
|
||||
#define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign)
|
||||
#define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign)
|
||||
#define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value))
|
||||
#define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1)
|
||||
#define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1)
|
||||
#define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff
|
||||
#define Dbl_setzero_exponent(dbl_value) \
|
||||
Dallp1(dbl_value) &= 0x800fffff
|
||||
#define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) &= 0xfff00000; \
|
||||
Dallp2(dbl_valueB) = 0
|
||||
#define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000
|
||||
#define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0
|
||||
#define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) &= 0x80000000; \
|
||||
Dallp2(dbl_valueB) = 0
|
||||
#define Dbl_setzero_exponentmantissap1(dbl_valueA) \
|
||||
Dallp1(dbl_valueA) &= 0x80000000
|
||||
#define Dbl_setzero(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0
|
||||
#define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0
|
||||
#define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0
|
||||
#define Dbl_setnegativezero(dbl_value) \
|
||||
Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0
|
||||
#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31
|
||||
|
||||
/* Use the following macro for both overflow & underflow conditions */
|
||||
#define ovfl -
|
||||
#define unfl +
|
||||
#define Dbl_setwrapped_exponent(dbl_value,exponent,op) \
|
||||
Deposit_dexponent(dbl_value,(exponent op DBL_WRAP))
|
||||
|
||||
#define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
|
||||
| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \
|
||||
Dallp2(dbl_valueB) = 0xFFFFFFFF
|
||||
#define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
|
||||
| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \
|
||||
| ((unsigned int)1<<31); \
|
||||
Dallp2(dbl_valueB) = 0xFFFFFFFF
|
||||
#define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \
|
||||
Deposit_dexponentmantissap1(dbl_valueA, \
|
||||
(((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
|
||||
| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \
|
||||
Dallp2(dbl_valueB) = 0xFFFFFFFF
|
||||
|
||||
#define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \
|
||||
Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) \
|
||||
<< (32-(1+DBL_EXP_LENGTH)) ; \
|
||||
Dallp2(dbl_valueB) = 0
|
||||
#define Dbl_setlargest(dbl_valueA,dbl_valueB,sign) \
|
||||
Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \
|
||||
((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) | \
|
||||
((1 << (32-(1+DBL_EXP_LENGTH))) - 1 ); \
|
||||
Dallp2(dbl_valueB) = 0xFFFFFFFF
|
||||
|
||||
|
||||
/* The high bit is always zero so arithmetic or logical shifts will work. */
|
||||
#define Dbl_right_align(srcdstA,srcdstB,shift,extent) \
|
||||
if( shift >= 32 ) \
|
||||
{ \
|
||||
/* Big shift requires examining the portion shift off \
|
||||
the end to properly set inexact. */ \
|
||||
if(shift < 64) \
|
||||
{ \
|
||||
if(shift > 32) \
|
||||
{ \
|
||||
Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \
|
||||
shift-32, Extall(extent)); \
|
||||
if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \
|
||||
} \
|
||||
else Extall(extent) = Dallp2(srcdstB); \
|
||||
Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Extall(extent) = Dallp1(srcdstA); \
|
||||
if(Dallp2(srcdstB)) Ext_setone_low(extent); \
|
||||
Dallp2(srcdstB) = 0; \
|
||||
} \
|
||||
Dallp1(srcdstA) = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Small alignment is simpler. Extension is easily set. */ \
|
||||
if (shift > 0) \
|
||||
{ \
|
||||
Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
|
||||
Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \
|
||||
Dallp2(srcdstB)); \
|
||||
Dallp1(srcdstA) >>= shift; \
|
||||
} \
|
||||
else Extall(extent) = 0; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we need to shift the result right to correct for an overshift
|
||||
* (due to the exponent becoming negative) during normalization.
|
||||
*/
|
||||
#define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \
|
||||
Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \
|
||||
Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \
|
||||
(Dallp2(srcdstB) >> (shift)); \
|
||||
Dallp1(srcdstA) = Dallp1(srcdstA) >> shift
|
||||
|
||||
#define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value)
|
||||
#define Dbl_hidden(dbl_value) Dhidden(dbl_value)
|
||||
#define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value)
|
||||
|
||||
/* The left argument is never smaller than the right argument */
|
||||
#define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
|
||||
if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \
|
||||
Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \
|
||||
Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta)
|
||||
|
||||
/* Subtract right augmented with extension from left augmented with zeros and
|
||||
* store into result and extension. */
|
||||
#define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \
|
||||
Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \
|
||||
if( (Extall(extent) = 0-Extall(extent)) ) \
|
||||
{ \
|
||||
if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \
|
||||
}
|
||||
|
||||
#define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \
|
||||
/* If the sum of the low words is less than either source, then \
|
||||
* an overflow into the next word occurred. */ \
|
||||
Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \
|
||||
if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \
|
||||
Dallp1(resulta)++
|
||||
|
||||
#define Dbl_xortointp1(left,right,result) \
|
||||
result = Dallp1(left) XOR Dallp1(right)
|
||||
|
||||
#define Dbl_xorfromintp1(left,right,result) \
|
||||
Dallp1(result) = left XOR Dallp1(right)
|
||||
|
||||
#define Dbl_swap_lower(left,right) \
|
||||
Dallp2(left) = Dallp2(left) XOR Dallp2(right); \
|
||||
Dallp2(right) = Dallp2(left) XOR Dallp2(right); \
|
||||
Dallp2(left) = Dallp2(left) XOR Dallp2(right)
|
||||
|
||||
/* Need to Initialize */
|
||||
#define Dbl_makequietnan(desta,destb) \
|
||||
Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
|
||||
| (1<<(32-(1+DBL_EXP_LENGTH+2))); \
|
||||
Dallp2(destb) = 0
|
||||
#define Dbl_makesignalingnan(desta,destb) \
|
||||
Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \
|
||||
| (1<<(32-(1+DBL_EXP_LENGTH+1))); \
|
||||
Dallp2(destb) = 0
|
||||
|
||||
#define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \
|
||||
while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \
|
||||
Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \
|
||||
exponent -= 8; \
|
||||
} \
|
||||
if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \
|
||||
Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \
|
||||
exponent -= 4; \
|
||||
} \
|
||||
while(Dbl_iszero_hidden(dbl_opndA)) { \
|
||||
Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \
|
||||
exponent -= 1; \
|
||||
}
|
||||
|
||||
#define Twoword_add(src1dstA,src1dstB,src2A,src2B) \
|
||||
/* \
|
||||
* want this macro to generate: \
|
||||
* ADD src1dstB,src2B,src1dstB; \
|
||||
* ADDC src1dstA,src2A,src1dstA; \
|
||||
*/ \
|
||||
if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \
|
||||
Dallp1(src1dstA) += (src2A); \
|
||||
Dallp2(src1dstB) += (src2B)
|
||||
|
||||
#define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \
|
||||
/* \
|
||||
* want this macro to generate: \
|
||||
* SUB src1dstB,src2B,src1dstB; \
|
||||
* SUBB src1dstA,src2A,src1dstA; \
|
||||
*/ \
|
||||
if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \
|
||||
Dallp1(src1dstA) -= (src2A); \
|
||||
Dallp2(src1dstB) -= (src2B)
|
||||
|
||||
#define Dbl_setoverflow(resultA,resultB) \
|
||||
/* set result to infinity or largest number */ \
|
||||
switch (Rounding_mode()) { \
|
||||
case ROUNDPLUS: \
|
||||
if (Dbl_isone_sign(resultA)) { \
|
||||
Dbl_setlargestnegative(resultA,resultB); \
|
||||
} \
|
||||
else { \
|
||||
Dbl_setinfinitypositive(resultA,resultB); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDMINUS: \
|
||||
if (Dbl_iszero_sign(resultA)) { \
|
||||
Dbl_setlargestpositive(resultA,resultB); \
|
||||
} \
|
||||
else { \
|
||||
Dbl_setinfinitynegative(resultA,resultB); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDNEAREST: \
|
||||
Dbl_setinfinity_exponentmantissa(resultA,resultB); \
|
||||
break; \
|
||||
case ROUNDZERO: \
|
||||
Dbl_setlargest_exponentmantissa(resultA,resultB); \
|
||||
}
|
||||
|
||||
#define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \
|
||||
Dbl_clear_signexponent_set_hidden(opndp1); \
|
||||
if (exponent >= (1-DBL_P)) { \
|
||||
if (exponent >= -31) { \
|
||||
guard = (Dallp2(opndp2) >> -exponent) & 1; \
|
||||
if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \
|
||||
if (exponent > -31) { \
|
||||
Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
|
||||
Dallp1(opndp1) >>= 1-exponent; \
|
||||
} \
|
||||
else { \
|
||||
Dallp2(opndp2) = Dallp1(opndp1); \
|
||||
Dbl_setzerop1(opndp1); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
guard = (Dallp1(opndp1) >> -32-exponent) & 1; \
|
||||
if (exponent == -32) sticky |= Dallp2(opndp2); \
|
||||
else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \
|
||||
Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \
|
||||
Dbl_setzerop1(opndp1); \
|
||||
} \
|
||||
inexact = guard | sticky; \
|
||||
} \
|
||||
else { \
|
||||
guard = 0; \
|
||||
sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \
|
||||
Dbl_setzero(opndp1,opndp2); \
|
||||
inexact = sticky; \
|
||||
}
|
||||
|
||||
/*
|
||||
* The fused multiply add instructions requires a double extended format,
|
||||
* with 106 bits of mantissa.
|
||||
*/
|
||||
#define DBLEXT_THRESHOLD 106
|
||||
|
||||
#define Dblext_setzero(valA,valB,valC,valD) \
|
||||
Dextallp1(valA) = 0; Dextallp2(valB) = 0; \
|
||||
Dextallp3(valC) = 0; Dextallp4(valD) = 0
|
||||
|
||||
|
||||
#define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0)
|
||||
#define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0)
|
||||
#define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0)
|
||||
#define Dblext_isone_highp3(val) (Dexthighp3(val)!=0)
|
||||
#define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0)
|
||||
#define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \
|
||||
Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0)
|
||||
|
||||
#define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \
|
||||
Dextallp1(desta) = Dextallp4(srca); \
|
||||
Dextallp2(destb) = Dextallp4(srcb); \
|
||||
Dextallp3(destc) = Dextallp4(srcc); \
|
||||
Dextallp4(destd) = Dextallp4(srcd)
|
||||
|
||||
#define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \
|
||||
Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
|
||||
Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
|
||||
Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \
|
||||
Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
|
||||
Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
|
||||
Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \
|
||||
Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
|
||||
Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \
|
||||
Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4)
|
||||
|
||||
#define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1)
|
||||
|
||||
/* The high bit is always zero so arithmetic or logical shifts will work. */
|
||||
#define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \
|
||||
{int shiftamt, sticky; \
|
||||
shiftamt = shift % 32; \
|
||||
sticky = 0; \
|
||||
switch (shift/32) { \
|
||||
case 0: if (shiftamt > 0) { \
|
||||
sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \
|
||||
Variable_shift_double(Dextallp3(srcdstC), \
|
||||
Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \
|
||||
Variable_shift_double(Dextallp2(srcdstB), \
|
||||
Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \
|
||||
Variable_shift_double(Dextallp1(srcdstA), \
|
||||
Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \
|
||||
Dextallp1(srcdstA) >>= shiftamt; \
|
||||
} \
|
||||
break; \
|
||||
case 1: if (shiftamt > 0) { \
|
||||
sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \
|
||||
Dextallp4(srcdstD); \
|
||||
Variable_shift_double(Dextallp2(srcdstB), \
|
||||
Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \
|
||||
Variable_shift_double(Dextallp1(srcdstA), \
|
||||
Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \
|
||||
} \
|
||||
else { \
|
||||
sticky = Dextallp4(srcdstD); \
|
||||
Dextallp4(srcdstD) = Dextallp3(srcdstC); \
|
||||
Dextallp3(srcdstC) = Dextallp2(srcdstB); \
|
||||
} \
|
||||
Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \
|
||||
Dextallp1(srcdstA) = 0; \
|
||||
break; \
|
||||
case 2: if (shiftamt > 0) { \
|
||||
sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \
|
||||
Dextallp3(srcdstC) | Dextallp4(srcdstD); \
|
||||
Variable_shift_double(Dextallp1(srcdstA), \
|
||||
Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \
|
||||
} \
|
||||
else { \
|
||||
sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \
|
||||
Dextallp4(srcdstD) = Dextallp2(srcdstB); \
|
||||
} \
|
||||
Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \
|
||||
Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
|
||||
break; \
|
||||
case 3: if (shiftamt > 0) { \
|
||||
sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \
|
||||
Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
|
||||
Dextallp4(srcdstD); \
|
||||
} \
|
||||
else { \
|
||||
sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \
|
||||
Dextallp4(srcdstD); \
|
||||
} \
|
||||
Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \
|
||||
Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \
|
||||
Dextallp3(srcdstC) = 0; \
|
||||
break; \
|
||||
} \
|
||||
if (sticky) Dblext_setone_lowmantissap4(srcdstD); \
|
||||
}
|
||||
|
||||
/* The left argument is never smaller than the right argument */
|
||||
#define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
|
||||
if( Dextallp4(rightd) > Dextallp4(leftd) ) \
|
||||
if( (Dextallp3(leftc)--) == 0) \
|
||||
if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
|
||||
Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \
|
||||
if( Dextallp3(rightc) > Dextallp3(leftc) ) \
|
||||
if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \
|
||||
Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \
|
||||
if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \
|
||||
Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \
|
||||
Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta)
|
||||
|
||||
#define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
|
||||
/* If the sum of the low words is less than either source, then \
|
||||
* an overflow into the next word occurred. */ \
|
||||
if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \
|
||||
Dextallp4(rightd)) \
|
||||
if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \
|
||||
Dextallp3(rightc)) \
|
||||
if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
|
||||
<= Dextallp2(rightb)) \
|
||||
Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
|
||||
else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
|
||||
else \
|
||||
if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
|
||||
Dextallp2(rightb)) \
|
||||
Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
|
||||
else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
|
||||
else \
|
||||
if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \
|
||||
Dextallp3(rightc)) \
|
||||
if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
|
||||
<= Dextallp2(rightb)) \
|
||||
Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
|
||||
else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
|
||||
else \
|
||||
if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
|
||||
Dextallp2(rightb)) \
|
||||
Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
|
||||
else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)
|
||||
|
||||
|
||||
#define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \
|
||||
Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \
|
||||
Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \
|
||||
Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \
|
||||
Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1
|
||||
|
||||
#define Dblext_leftshiftby8(valA,valB,valC,valD) \
|
||||
Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \
|
||||
Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \
|
||||
Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \
|
||||
Dextallp4(valD) <<= 8
|
||||
#define Dblext_leftshiftby4(valA,valB,valC,valD) \
|
||||
Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \
|
||||
Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \
|
||||
Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \
|
||||
Dextallp4(valD) <<= 4
|
||||
#define Dblext_leftshiftby3(valA,valB,valC,valD) \
|
||||
Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \
|
||||
Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \
|
||||
Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \
|
||||
Dextallp4(valD) <<= 3
|
||||
#define Dblext_leftshiftby2(valA,valB,valC,valD) \
|
||||
Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \
|
||||
Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \
|
||||
Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \
|
||||
Dextallp4(valD) <<= 2
|
||||
#define Dblext_leftshiftby1(valA,valB,valC,valD) \
|
||||
Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \
|
||||
Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \
|
||||
Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \
|
||||
Dextallp4(valD) <<= 1
|
||||
|
||||
#define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \
|
||||
Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \
|
||||
Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \
|
||||
Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \
|
||||
Dextallp1(valueA) >>= 4
|
||||
#define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \
|
||||
Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \
|
||||
Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \
|
||||
Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \
|
||||
Dextallp1(valueA) >>= 1
|
||||
|
||||
#define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result)
|
||||
|
||||
#define Dblext_xorfromintp1(left,right,result) \
|
||||
Dbl_xorfromintp1(left,right,result)
|
||||
|
||||
#define Dblext_copytoint_exponentmantissap1(src,dest) \
|
||||
Dbl_copytoint_exponentmantissap1(src,dest)
|
||||
|
||||
#define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
|
||||
Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright)
|
||||
|
||||
#define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \
|
||||
Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \
|
||||
Dextallp3(dest3) = 0; Dextallp4(dest4) = 0
|
||||
|
||||
#define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign)
|
||||
#define Dblext_clear_signexponent_set_hidden(srcdst) \
|
||||
Dbl_clear_signexponent_set_hidden(srcdst)
|
||||
#define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst)
|
||||
#define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst)
|
||||
#define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value)
|
||||
|
||||
/*
|
||||
* The Fourword_add() macro assumes that integers are 4 bytes in size.
|
||||
* It will break if this is not the case.
|
||||
*/
|
||||
|
||||
#define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \
|
||||
/* \
|
||||
* want this macro to generate: \
|
||||
* ADD src1dstD,src2D,src1dstD; \
|
||||
* ADDC src1dstC,src2C,src1dstC; \
|
||||
* ADDC src1dstB,src2B,src1dstB; \
|
||||
* ADDC src1dstA,src2A,src1dstA; \
|
||||
*/ \
|
||||
if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \
|
||||
if ((unsigned int)(src1dstC += (src2C) + 1) <= \
|
||||
(unsigned int)(src2C)) { \
|
||||
if ((unsigned int)(src1dstB += (src2B) + 1) <= \
|
||||
(unsigned int)(src2B)) src1dstA++; \
|
||||
} \
|
||||
else if ((unsigned int)(src1dstB += (src2B)) < \
|
||||
(unsigned int)(src2B)) src1dstA++; \
|
||||
} \
|
||||
else { \
|
||||
if ((unsigned int)(src1dstC += (src2C)) < \
|
||||
(unsigned int)(src2C)) { \
|
||||
if ((unsigned int)(src1dstB += (src2B) + 1) <= \
|
||||
(unsigned int)(src2B)) src1dstA++; \
|
||||
} \
|
||||
else if ((unsigned int)(src1dstB += (src2B)) < \
|
||||
(unsigned int)(src2B)) src1dstA++; \
|
||||
} \
|
||||
src1dstA += (src2A)
|
||||
|
||||
#define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \
|
||||
{int shiftamt, sticky; \
|
||||
is_tiny = TRUE; \
|
||||
if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \
|
||||
switch (Rounding_mode()) { \
|
||||
case ROUNDPLUS: \
|
||||
if (Dbl_iszero_sign(opndp1)) { \
|
||||
Dbl_increment(opndp1,opndp2); \
|
||||
if (Dbl_isone_hiddenoverflow(opndp1)) \
|
||||
is_tiny = FALSE; \
|
||||
Dbl_decrement(opndp1,opndp2); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDMINUS: \
|
||||
if (Dbl_isone_sign(opndp1)) { \
|
||||
Dbl_increment(opndp1,opndp2); \
|
||||
if (Dbl_isone_hiddenoverflow(opndp1)) \
|
||||
is_tiny = FALSE; \
|
||||
Dbl_decrement(opndp1,opndp2); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDNEAREST: \
|
||||
if (Dblext_isone_highp3(opndp3) && \
|
||||
(Dblext_isone_lowp2(opndp2) || \
|
||||
Dblext_isnotzero_low31p3(opndp3))) { \
|
||||
Dbl_increment(opndp1,opndp2); \
|
||||
if (Dbl_isone_hiddenoverflow(opndp1)) \
|
||||
is_tiny = FALSE; \
|
||||
Dbl_decrement(opndp1,opndp2); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
Dblext_clear_signexponent_set_hidden(opndp1); \
|
||||
if (exponent >= (1-QUAD_P)) { \
|
||||
shiftamt = (1-exponent) % 32; \
|
||||
switch((1-exponent)/32) { \
|
||||
case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \
|
||||
Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \
|
||||
Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \
|
||||
Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \
|
||||
Dextallp1(opndp1) >>= shiftamt; \
|
||||
break; \
|
||||
case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \
|
||||
Dextallp4(opndp4); \
|
||||
Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \
|
||||
Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \
|
||||
Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \
|
||||
Dextallp1(opndp1) = 0; \
|
||||
break; \
|
||||
case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \
|
||||
Dextallp3(opndp3) | Dextallp4(opndp4); \
|
||||
Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \
|
||||
Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \
|
||||
Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
|
||||
break; \
|
||||
case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \
|
||||
Dextallp2(opndp2) | Dextallp3(opndp3) | \
|
||||
Dextallp4(opndp4); \
|
||||
Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \
|
||||
Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \
|
||||
Dextallp3(opndp3) = 0; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \
|
||||
Dextallp3(opndp3) | Dextallp4(opndp4); \
|
||||
Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \
|
||||
} \
|
||||
if (sticky) Dblext_setone_lowmantissap4(opndp4); \
|
||||
exponent = 0; \
|
||||
}
|
368
arch/parisc/math-emu/decode_exc.c
Обычный файл
368
arch/parisc/math-emu/decode_exc.c
Обычный файл
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/fp/decode_exc.c $ Revision: $
|
||||
*
|
||||
* Purpose:
|
||||
* <<please update with a synopsis of the functionality provided by this file>>
|
||||
*
|
||||
* External Interfaces:
|
||||
* <<the following list was autogenerated, please review>>
|
||||
* decode_fpu(Fpu_register, trap_counts)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
* <<please update>>
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
/* #include "types.h" */
|
||||
#include <asm/signal.h>
|
||||
#include <asm/siginfo.h>
|
||||
/* #include <machine/sys/mdep_private.h> */
|
||||
|
||||
#undef Fpustatus_register
|
||||
#define Fpustatus_register Fpu_register[0]
|
||||
|
||||
/* General definitions */
|
||||
#define DOESTRAP 1
|
||||
#define NOTRAP 0
|
||||
#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
|
||||
#define copropbit 1<<31-2 /* bit position 2 */
|
||||
#define opclass 9 /* bits 21 & 22 */
|
||||
#define fmt 11 /* bits 19 & 20 */
|
||||
#define df 13 /* bits 17 & 18 */
|
||||
#define twobits 3 /* mask low-order 2 bits */
|
||||
#define fivebits 31 /* mask low-order 5 bits */
|
||||
#define MAX_EXCP_REG 7 /* number of excpeption registers to check */
|
||||
|
||||
/* Exception register definitions */
|
||||
#define Excp_type(index) Exceptiontype(Fpu_register[index])
|
||||
#define Excp_instr(index) Instructionfield(Fpu_register[index])
|
||||
#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
|
||||
#define Excp_format() \
|
||||
(current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
|
||||
|
||||
/* Miscellaneous definitions */
|
||||
#define Fpu_sgl(index) Fpu_register[index*2]
|
||||
|
||||
#define Fpu_dblp1(index) Fpu_register[index*2]
|
||||
#define Fpu_dblp2(index) Fpu_register[(index*2)+1]
|
||||
|
||||
#define Fpu_quadp1(index) Fpu_register[index*2]
|
||||
#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
|
||||
#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
|
||||
#define Fpu_quadp4(index) Fpu_register[(index*2)+3]
|
||||
|
||||
/* Single precision floating-point definitions */
|
||||
#ifndef Sgl_decrement
|
||||
# define Sgl_decrement(sgl_value) Sall(sgl_value)--
|
||||
#endif
|
||||
|
||||
/* Double precision floating-point definitions */
|
||||
#ifndef Dbl_decrement
|
||||
# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
|
||||
if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)--
|
||||
#endif
|
||||
|
||||
|
||||
#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \
|
||||
aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \
|
||||
Fpu_register[0] |= bflags; \
|
||||
}
|
||||
|
||||
u_int
|
||||
decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
|
||||
{
|
||||
unsigned int current_ir, excp;
|
||||
int target, exception_index = 1;
|
||||
boolean inexact;
|
||||
unsigned int aflags;
|
||||
unsigned int bflags;
|
||||
unsigned int excptype;
|
||||
|
||||
|
||||
/* Keep stats on how many floating point exceptions (based on type)
|
||||
* that happen. Want to keep this overhead low, but still provide
|
||||
* some information to the customer. All exits from this routine
|
||||
* need to restore Fpu_register[0]
|
||||
*/
|
||||
|
||||
bflags=(Fpu_register[0] & 0xf8000000);
|
||||
Fpu_register[0] &= 0x07ffffff;
|
||||
|
||||
/* exception_index is used to index the exception register queue. It
|
||||
* always points at the last register that contains a valid exception. A
|
||||
* zero value implies no exceptions (also the initialized value). Setting
|
||||
* the T-bit resets the exception_index to zero.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check for reserved-op exception. A reserved-op exception does not
|
||||
* set any exception registers nor does it set the T-bit. If the T-bit
|
||||
* is not set then a reserved-op exception occurred.
|
||||
*
|
||||
* At some point, we may want to report reserved op exceptions as
|
||||
* illegal instructions.
|
||||
*/
|
||||
|
||||
if (!Is_tbit_set()) {
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
return SIGNALCODE(SIGILL, ILL_COPROC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is a coprocessor op.
|
||||
*
|
||||
* Now we need to determine what type of exception occurred.
|
||||
*/
|
||||
for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
|
||||
current_ir = Excp_instr(exception_index);
|
||||
/*
|
||||
* On PA89: there are 5 different unimplemented exception
|
||||
* codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds
|
||||
* another, 0x2b. Only these have the low order bit set.
|
||||
*/
|
||||
excptype = Excp_type(exception_index);
|
||||
if (excptype & UNIMPLEMENTEDEXCEPTION) {
|
||||
/*
|
||||
* Clear T-bit and exception register so that
|
||||
* we can tell if a trap really occurs while
|
||||
* emulating the instruction.
|
||||
*/
|
||||
Clear_tbit();
|
||||
Clear_excp_register(exception_index);
|
||||
/*
|
||||
* Now emulate this instruction. If a trap occurs,
|
||||
* fpudispatch will return a non-zero number
|
||||
*/
|
||||
excp = fpudispatch(current_ir,excptype,0,Fpu_register);
|
||||
/* accumulate the status flags, don't lose them as in hpux */
|
||||
if (excp) {
|
||||
/*
|
||||
* We now need to make sure that the T-bit and the
|
||||
* exception register contain the correct values
|
||||
* before continuing.
|
||||
*/
|
||||
/*
|
||||
* Set t-bit since it might still be needed for a
|
||||
* subsequent real trap (I don't understand fully -PB)
|
||||
*/
|
||||
Set_tbit();
|
||||
/* some of the following code uses
|
||||
* Excp_type(exception_index) so fix that up */
|
||||
Set_exceptiontype_and_instr_field(excp,current_ir,
|
||||
Fpu_register[exception_index]);
|
||||
if (excp == UNIMPLEMENTEDEXCEPTION) {
|
||||
/*
|
||||
* it is really unimplemented, so restore the
|
||||
* TIMEX extended unimplemented exception code
|
||||
*/
|
||||
excp = excptype;
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
return SIGNALCODE(SIGILL, ILL_COPROC);
|
||||
}
|
||||
/* some of the following code uses excptype, so
|
||||
* fix that up too */
|
||||
excptype = excp;
|
||||
}
|
||||
/* handle exceptions other than the real UNIMPLIMENTED the
|
||||
* same way as if the hardware had caused them */
|
||||
if (excp == NOEXCEPTION)
|
||||
/* For now use 'break', should technically be 'continue' */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* In PA89, the underflow exception has been extended to encode
|
||||
* additional information. The exception looks like pp01x0,
|
||||
* where x is 1 if inexact and pp represent the inexact bit (I)
|
||||
* and the round away bit (RA)
|
||||
*/
|
||||
if (excptype & UNDERFLOWEXCEPTION) {
|
||||
/* check for underflow trap enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTUND);
|
||||
} else {
|
||||
/*
|
||||
* Isn't a real trap; we need to
|
||||
* return the default value.
|
||||
*/
|
||||
target = current_ir & fivebits;
|
||||
#ifndef lint
|
||||
if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
|
||||
else inexact = FALSE;
|
||||
#endif
|
||||
switch (Excp_format()) {
|
||||
case SGL:
|
||||
/*
|
||||
* If ra (round-away) is set, will
|
||||
* want to undo the rounding done
|
||||
* by the hardware.
|
||||
*/
|
||||
if (Rabit(Fpu_register[exception_index]))
|
||||
Sgl_decrement(Fpu_sgl(target));
|
||||
|
||||
/* now denormalize */
|
||||
sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
|
||||
break;
|
||||
case DBL:
|
||||
/*
|
||||
* If ra (round-away) is set, will
|
||||
* want to undo the rounding done
|
||||
* by the hardware.
|
||||
*/
|
||||
if (Rabit(Fpu_register[exception_index]))
|
||||
Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
|
||||
|
||||
/* now denormalize */
|
||||
dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
|
||||
&inexact,Rounding_mode());
|
||||
break;
|
||||
}
|
||||
if (inexact) Set_underflowflag();
|
||||
/*
|
||||
* Underflow can generate an inexact
|
||||
* exception. If inexact trap is enabled,
|
||||
* want to do an inexact trap, otherwise
|
||||
* set inexact flag.
|
||||
*/
|
||||
if (inexact && Is_inexacttrap_enabled()) {
|
||||
/*
|
||||
* Set exception field of exception register
|
||||
* to inexact, parm field to zero.
|
||||
* Underflow bit should be cleared.
|
||||
*/
|
||||
Set_exceptiontype(Fpu_register[exception_index],
|
||||
INEXACTEXCEPTION);
|
||||
Set_parmfield(Fpu_register[exception_index],0);
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTRES);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Exception register needs to be cleared.
|
||||
* Inexact flag needs to be set if inexact.
|
||||
*/
|
||||
Clear_excp_register(exception_index);
|
||||
if (inexact) Set_inexactflag();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch(Excp_type(exception_index)) {
|
||||
case OVERFLOWEXCEPTION:
|
||||
case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
|
||||
/* check for overflow trap enabled */
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTOVF);
|
||||
} else {
|
||||
/*
|
||||
* Isn't a real trap; we need to
|
||||
* return the default value.
|
||||
*/
|
||||
target = current_ir & fivebits;
|
||||
switch (Excp_format()) {
|
||||
case SGL:
|
||||
Sgl_setoverflow(Fpu_sgl(target));
|
||||
break;
|
||||
case DBL:
|
||||
Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
|
||||
break;
|
||||
}
|
||||
Set_overflowflag();
|
||||
/*
|
||||
* Overflow always generates an inexact
|
||||
* exception. If inexact trap is enabled,
|
||||
* want to do an inexact trap, otherwise
|
||||
* set inexact flag.
|
||||
*/
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
/*
|
||||
* Set exception field of exception
|
||||
* register to inexact. Overflow
|
||||
* bit should be cleared.
|
||||
*/
|
||||
Set_exceptiontype(Fpu_register[exception_index],
|
||||
INEXACTEXCEPTION);
|
||||
update_trap_counts(Fpu_register, aflags, bflags,
|
||||
trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTRES);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Exception register needs to be cleared.
|
||||
* Inexact flag needs to be set.
|
||||
*/
|
||||
Clear_excp_register(exception_index);
|
||||
Set_inexactflag();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INVALIDEXCEPTION:
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTINV);
|
||||
case DIVISIONBYZEROEXCEPTION:
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTDIV);
|
||||
case INEXACTEXCEPTION:
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
return SIGNALCODE(SIGFPE, FPE_FLTRES);
|
||||
default:
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
|
||||
__LINE__, Excp_type(exception_index));
|
||||
return SIGNALCODE(SIGILL, ILL_COPROC);
|
||||
case NOEXCEPTION: /* no exception */
|
||||
/*
|
||||
* Clear exception register in case
|
||||
* other fields are non-zero.
|
||||
*/
|
||||
Clear_excp_register(exception_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* No real exceptions occurred.
|
||||
*/
|
||||
Clear_tbit();
|
||||
update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
|
||||
return(NOTRAP);
|
||||
}
|
135
arch/parisc/math-emu/denormal.c
Обычный файл
135
arch/parisc/math-emu/denormal.c
Обычный файл
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/fp/denormal.c $ Revision: $
|
||||
*
|
||||
* Purpose:
|
||||
* <<please update with a synopsis of the functionality provided by this file>>
|
||||
*
|
||||
* External Interfaces:
|
||||
* <<the following list was autogenerated, please review>>
|
||||
* dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
|
||||
* sgl_denormalize(sgl_opnd,inexactflag,rmode)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
* <<please update>>
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "hppa.h"
|
||||
#include <linux/kernel.h>
|
||||
/* #include <machine/sys/mdep_private.h> */
|
||||
|
||||
#undef Fpustatus_register
|
||||
#define Fpustatus_register Fpu_register[0]
|
||||
|
||||
void
|
||||
sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
|
||||
{
|
||||
unsigned int opnd;
|
||||
int sign, exponent;
|
||||
boolean guardbit = FALSE, stickybit, inexact;
|
||||
|
||||
opnd = *sgl_opnd;
|
||||
stickybit = *inexactflag;
|
||||
exponent = Sgl_exponent(opnd) - SGL_WRAP;
|
||||
sign = Sgl_sign(opnd);
|
||||
Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
|
||||
if (inexact) {
|
||||
switch (rmode) {
|
||||
case ROUNDPLUS:
|
||||
if (sign == 0) {
|
||||
Sgl_increment(opnd);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (sign != 0) {
|
||||
Sgl_increment(opnd);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Sgl_isone_lowmantissa(opnd))) {
|
||||
Sgl_increment(opnd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Sgl_set_sign(opnd,sign);
|
||||
*sgl_opnd = opnd;
|
||||
*inexactflag = inexact;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
dbl_denormalize(unsigned int *dbl_opndp1,
|
||||
unsigned int * dbl_opndp2,
|
||||
boolean *inexactflag,
|
||||
int rmode)
|
||||
{
|
||||
unsigned int opndp1, opndp2;
|
||||
int sign, exponent;
|
||||
boolean guardbit = FALSE, stickybit, inexact;
|
||||
|
||||
opndp1 = *dbl_opndp1;
|
||||
opndp2 = *dbl_opndp2;
|
||||
stickybit = *inexactflag;
|
||||
exponent = Dbl_exponent(opndp1) - DBL_WRAP;
|
||||
sign = Dbl_sign(opndp1);
|
||||
Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
|
||||
if (inexact) {
|
||||
switch (rmode) {
|
||||
case ROUNDPLUS:
|
||||
if (sign == 0) {
|
||||
Dbl_increment(opndp1,opndp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (sign != 0) {
|
||||
Dbl_increment(opndp1,opndp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opndp2))) {
|
||||
Dbl_increment(opndp1,opndp2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dbl_set_sign(opndp1,sign);
|
||||
*dbl_opndp1 = opndp1;
|
||||
*dbl_opndp2 = opndp2;
|
||||
*inexactflag = inexact;
|
||||
return;
|
||||
}
|
524
arch/parisc/math-emu/dfadd.c
Обычный файл
524
arch/parisc/math-emu/dfadd.c
Обычный файл
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfadd.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double_add: add two double precision values.
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fadd(leftptr, rightptr, dstptr, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double_add: add two double precision values.
|
||||
*/
|
||||
dbl_fadd(
|
||||
dbl_floating_point *leftptr,
|
||||
dbl_floating_point *rightptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int signless_upper_left, signless_upper_right, save;
|
||||
register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
|
||||
register unsigned int resultp1 = 0, resultp2 = 0;
|
||||
|
||||
register int result_exponent, right_exponent, diff_exponent;
|
||||
register int sign_save, jumpsize;
|
||||
register boolean inexact = FALSE;
|
||||
register boolean underflowtrap;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
Dbl_copyfromptr(leftptr,leftp1,leftp2);
|
||||
Dbl_copyfromptr(rightptr,rightp1,rightp2);
|
||||
|
||||
/* A zero "save" helps discover equal operands (for later), *
|
||||
* and is used in swapping operands (if needed). */
|
||||
Dbl_xortointp1(leftp1,rightp1,/*to*/save);
|
||||
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
|
||||
{
|
||||
if (Dbl_iszero_mantissa(leftp1,leftp2))
|
||||
{
|
||||
if (Dbl_isnotnan(rightp1,rightp2))
|
||||
{
|
||||
if (Dbl_isinfinity(rightp1,rightp2) && save!=0)
|
||||
{
|
||||
/*
|
||||
* invalid since operands are opposite signed infinity's
|
||||
*/
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(leftp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(leftp1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Dbl_is_signalingnan(rightp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(rightp1);
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
} /* End left NaN or Infinity processing */
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(rightp1))
|
||||
{
|
||||
if (Dbl_iszero_mantissa(rightp1,rightp2))
|
||||
{
|
||||
/* return infinity */
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(rightp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(rightp1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
} /* End right NaN or Infinity processing */
|
||||
|
||||
/* Invariant: Must be dealing with finite numbers */
|
||||
|
||||
/* Compare operands by removing the sign */
|
||||
Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
|
||||
Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
|
||||
|
||||
/* sign difference selects add or sub operation. */
|
||||
if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
|
||||
{
|
||||
/* Set the left operand to the larger one by XOR swap *
|
||||
* First finish the first word using "save" */
|
||||
Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
|
||||
Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
|
||||
Dbl_swap_lower(leftp2,rightp2);
|
||||
result_exponent = Dbl_exponent(leftp1);
|
||||
}
|
||||
/* Invariant: left is not smaller than right. */
|
||||
|
||||
if((right_exponent = Dbl_exponent(rightp1)) == 0)
|
||||
{
|
||||
/* Denormalized operands. First look for zeroes */
|
||||
if(Dbl_iszero_mantissa(rightp1,rightp2))
|
||||
{
|
||||
/* right is zero */
|
||||
if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
|
||||
{
|
||||
/* Both operands are zeros */
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Dbl_or_signs(leftp1,/*with*/rightp1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_and_signs(leftp1,/*with*/rightp1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left is not a zero and must be the result. Trapped
|
||||
* underflows are signaled if left is denormalized. Result
|
||||
* is always exact. */
|
||||
if( (result_exponent == 0) && Is_underflowtrap_enabled() )
|
||||
{
|
||||
/* need to normalize results mantissa */
|
||||
sign_save = Dbl_signextendedsign(leftp1);
|
||||
Dbl_leftshiftby1(leftp1,leftp2);
|
||||
Dbl_normalize(leftp1,leftp2,result_exponent);
|
||||
Dbl_set_sign(leftp1,/*using*/sign_save);
|
||||
Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
}
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/* Neither are zeroes */
|
||||
Dbl_clear_sign(rightp1); /* Exponent is already cleared */
|
||||
if(result_exponent == 0 )
|
||||
{
|
||||
/* Both operands are denormalized. The result must be exact
|
||||
* and is simply calculated. A sum could become normalized and a
|
||||
* difference could cancel to a true zero. */
|
||||
if( (/*signed*/int) save < 0 )
|
||||
{
|
||||
Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
|
||||
/*into*/resultp1,resultp2);
|
||||
if(Dbl_iszero_mantissa(resultp1,resultp2))
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Dbl_setone_sign(resultp1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_setzero_sign(resultp1);
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_addition(leftp1,leftp2,rightp1,rightp2,
|
||||
/*into*/resultp1,resultp2);
|
||||
if(Dbl_isone_hidden(resultp1))
|
||||
{
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
/* need to normalize result */
|
||||
sign_save = Dbl_signextendedsign(resultp1);
|
||||
Dbl_leftshiftby1(resultp1,resultp2);
|
||||
Dbl_normalize(resultp1,resultp2,result_exponent);
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
right_exponent = 1; /* Set exponent to reflect different bias
|
||||
* with denomalized numbers. */
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_clear_signexponent_set_hidden(rightp1);
|
||||
}
|
||||
Dbl_clear_exponent_set_hidden(leftp1);
|
||||
diff_exponent = result_exponent - right_exponent;
|
||||
|
||||
/*
|
||||
* Special case alignment of operands that would force alignment
|
||||
* beyond the extent of the extension. A further optimization
|
||||
* could special case this but only reduces the path length for this
|
||||
* infrequent case.
|
||||
*/
|
||||
if(diff_exponent > DBL_THRESHOLD)
|
||||
{
|
||||
diff_exponent = DBL_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Align right operand by shifting to right */
|
||||
Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
|
||||
/*and lower to*/extent);
|
||||
|
||||
/* Treat sum and difference of the operands separately. */
|
||||
if( (/*signed*/int) save < 0 )
|
||||
{
|
||||
/*
|
||||
* Difference of the two operands. Their can be no overflow. A
|
||||
* borrow can occur out of the hidden bit and force a post
|
||||
* normalization phase.
|
||||
*/
|
||||
Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
|
||||
/*with*/extent,/*into*/resultp1,resultp2);
|
||||
if(Dbl_iszero_hidden(resultp1))
|
||||
{
|
||||
/* Handle normalization */
|
||||
/* A straight foward algorithm would now shift the result
|
||||
* and extension left until the hidden bit becomes one. Not
|
||||
* all of the extension bits need participate in the shift.
|
||||
* Only the two most significant bits (round and guard) are
|
||||
* needed. If only a single shift is needed then the guard
|
||||
* bit becomes a significant low order bit and the extension
|
||||
* must participate in the rounding. If more than a single
|
||||
* shift is needed, then all bits to the right of the guard
|
||||
* bit are zeros, and the guard bit may or may not be zero. */
|
||||
sign_save = Dbl_signextendedsign(resultp1);
|
||||
Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
|
||||
|
||||
/* Need to check for a zero result. The sign and exponent
|
||||
* fields have already been zeroed. The more efficient test
|
||||
* of the full object can be used.
|
||||
*/
|
||||
if(Dbl_iszero(resultp1,resultp2))
|
||||
/* Must have been "x-x" or "x+(-x)". */
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
result_exponent--;
|
||||
/* Look to see if normalization is finished. */
|
||||
if(Dbl_isone_hidden(resultp1))
|
||||
{
|
||||
if(result_exponent==0)
|
||||
{
|
||||
/* Denormalized, exponent should be zero. Left operand *
|
||||
* was normalized, so extent (guard, round) was zero */
|
||||
goto underflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No further normalization is needed. */
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Ext_leftshiftby1(extent);
|
||||
goto round;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for denormalized, exponent should be zero. Left *
|
||||
* operand was normalized, so extent (guard, round) was zero */
|
||||
if(!(underflowtrap = Is_underflowtrap_enabled()) &&
|
||||
result_exponent==0) goto underflow;
|
||||
|
||||
/* Shift extension to complete one bit of normalization and
|
||||
* update exponent. */
|
||||
Ext_leftshiftby1(extent);
|
||||
|
||||
/* Discover first one bit to determine shift amount. Use a
|
||||
* modified binary search. We have already shifted the result
|
||||
* one position right and still not found a one so the remainder
|
||||
* of the extension must be zero and simplifies rounding. */
|
||||
/* Scan bytes */
|
||||
while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
|
||||
{
|
||||
Dbl_leftshiftby8(resultp1,resultp2);
|
||||
if((result_exponent -= 8) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Now narrow it down to the nibble */
|
||||
if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
|
||||
{
|
||||
/* The lower nibble contains the normalizing one */
|
||||
Dbl_leftshiftby4(resultp1,resultp2);
|
||||
if((result_exponent -= 4) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Select case were first bit is set (already normalized)
|
||||
* otherwise select the proper shift. */
|
||||
if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
|
||||
{
|
||||
/* Already normalized */
|
||||
if(result_exponent <= 0) goto underflow;
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Dbl_set_exponent(resultp1,/*using*/result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_sethigh4bits(resultp1,/*using*/sign_save);
|
||||
switch(jumpsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Dbl_leftshiftby3(resultp1,resultp2);
|
||||
result_exponent -= 3;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
Dbl_leftshiftby2(resultp1,resultp2);
|
||||
result_exponent -= 2;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
Dbl_leftshiftby1(resultp1,resultp2);
|
||||
result_exponent -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result_exponent > 0)
|
||||
{
|
||||
Dbl_set_exponent(resultp1,/*using*/result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION); /* Sign bit is already set */
|
||||
}
|
||||
/* Fixup potential underflows */
|
||||
underflow:
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
Dbl_set_sign(resultp1,sign_save);
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Since we cannot get an inexact denormalized result,
|
||||
* we can now return.
|
||||
*/
|
||||
Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
|
||||
Dbl_clear_signexponent(resultp1);
|
||||
Dbl_set_sign(resultp1,sign_save);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
} /* end if(hidden...)... */
|
||||
/* Fall through and round */
|
||||
} /* end if(save < 0)... */
|
||||
else
|
||||
{
|
||||
/* Add magnitudes */
|
||||
Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
|
||||
if(Dbl_isone_hiddenoverflow(resultp1))
|
||||
{
|
||||
/* Prenormalization required. */
|
||||
Dbl_rightshiftby1_withextent(resultp2,extent,extent);
|
||||
Dbl_arithrightshiftby1(resultp1,resultp2);
|
||||
result_exponent++;
|
||||
} /* end if hiddenoverflow... */
|
||||
} /* end else ...add magnitudes... */
|
||||
|
||||
/* Round the result. If the extension is all zeros,then the result is
|
||||
* exact. Otherwise round in the correct direction. No underflow is
|
||||
* possible. If a postnormalization is necessary, then the mantissa is
|
||||
* all zeros so no shift is needed. */
|
||||
round:
|
||||
if(Ext_isnotzero(extent))
|
||||
{
|
||||
inexact = TRUE;
|
||||
switch(Rounding_mode())
|
||||
{
|
||||
case ROUNDNEAREST: /* The default. */
|
||||
if(Ext_isone_sign(extent))
|
||||
{
|
||||
/* at least 1/2 ulp */
|
||||
if(Ext_isnotzero_lower(extent) ||
|
||||
Dbl_isone_lowmantissap2(resultp2))
|
||||
{
|
||||
/* either exactly half way and odd or more than 1/2ulp */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDPLUS:
|
||||
if(Dbl_iszero_sign(resultp1))
|
||||
{
|
||||
/* Round up positive results */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDMINUS:
|
||||
if(Dbl_isone_sign(resultp1))
|
||||
{
|
||||
/* Round down negative results */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
|
||||
case ROUNDZERO:;
|
||||
/* truncate is simple */
|
||||
} /* end switch... */
|
||||
if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
|
||||
}
|
||||
if(result_exponent == DBL_INFINITY_EXPONENT)
|
||||
{
|
||||
/* Overflow */
|
||||
if(Is_overflowtrap_enabled())
|
||||
{
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
inexact = TRUE;
|
||||
Set_overflowflag();
|
||||
Dbl_setoverflow(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
else Dbl_set_exponent(resultp1,result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if(inexact)
|
||||
if(Is_inexacttrap_enabled())
|
||||
return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(NOEXCEPTION);
|
||||
}
|
181
arch/parisc/math-emu/dfcmp.c
Обычный файл
181
arch/parisc/math-emu/dfcmp.c
Обычный файл
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfcmp.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* dbl_cmp: compare two values
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fcmp(leftptr, rightptr, cond, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* dbl_cmp: compare two values
|
||||
*/
|
||||
int
|
||||
dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
|
||||
unsigned int cond, unsigned int *status)
|
||||
|
||||
/* The predicate to be tested */
|
||||
|
||||
{
|
||||
register unsigned int leftp1, leftp2, rightp1, rightp2;
|
||||
register int xorresult;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
Dbl_copyfromptr(leftptr,leftp1,leftp2);
|
||||
Dbl_copyfromptr(rightptr,rightp1,rightp2);
|
||||
/*
|
||||
* Test for NaN
|
||||
*/
|
||||
if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
|
||||
|| (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
|
||||
{
|
||||
/* Check if a NaN is involved. Signal an invalid exception when
|
||||
* comparing a signaling NaN or when comparing quiet NaNs and the
|
||||
* low bit of the condition is set */
|
||||
if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
|
||||
&& Dbl_isnotzero_mantissa(leftp1,leftp2)
|
||||
&& (Exception(cond) || Dbl_isone_signaling(leftp1)))
|
||||
||
|
||||
((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
|
||||
&& Dbl_isnotzero_mantissa(rightp1,rightp2)
|
||||
&& (Exception(cond) || Dbl_isone_signaling(rightp1))) )
|
||||
{
|
||||
if( Is_invalidtrap_enabled() ) {
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
else Set_invalidflag();
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* All the exceptional conditions are handled, now special case
|
||||
NaN compares */
|
||||
else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
|
||||
&& Dbl_isnotzero_mantissa(leftp1,leftp2))
|
||||
||
|
||||
((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
|
||||
&& Dbl_isnotzero_mantissa(rightp1,rightp2)) )
|
||||
{
|
||||
/* NaNs always compare unordered. */
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* infinities will drop down to the normal compare mechanisms */
|
||||
}
|
||||
/* First compare for unequal signs => less or greater or
|
||||
* special equal case */
|
||||
Dbl_xortointp1(leftp1,rightp1,xorresult);
|
||||
if( xorresult < 0 )
|
||||
{
|
||||
/* left negative => less, left positive => greater.
|
||||
* equal is possible if both operands are zeros. */
|
||||
if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
|
||||
&& Dbl_iszero_exponentmantissa(rightp1,rightp2) )
|
||||
{
|
||||
Set_status_cbit(Equal(cond));
|
||||
}
|
||||
else if( Dbl_isone_sign(leftp1) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
/* Signs are the same. Treat negative numbers separately
|
||||
* from the positives because of the reversed sense. */
|
||||
else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
|
||||
{
|
||||
Set_status_cbit(Equal(cond));
|
||||
}
|
||||
else if( Dbl_iszero_sign(leftp1) )
|
||||
{
|
||||
/* Positive compare */
|
||||
if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Equal first parts. Now we must use unsigned compares to
|
||||
* resolve the two possibilities. */
|
||||
if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Negative compare. Signed or unsigned compares
|
||||
* both work the same. That distinction is only
|
||||
* important when the sign bits differ. */
|
||||
if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Equal first parts. Now we must use unsigned compares to
|
||||
* resolve the two possibilities. */
|
||||
if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
400
arch/parisc/math-emu/dfdiv.c
Обычный файл
400
arch/parisc/math-emu/dfdiv.c
Обычный файл
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfdiv.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double Precision Floating-point Divide
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fdiv(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double Precision Floating-point Divide
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
|
||||
dbl_floating_point * dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
|
||||
register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
|
||||
register int dest_exponent, count;
|
||||
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
|
||||
boolean is_tiny;
|
||||
|
||||
Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
|
||||
Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
|
||||
/*
|
||||
* set sign bit of result
|
||||
*/
|
||||
if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
|
||||
Dbl_setnegativezerop1(resultp1);
|
||||
else Dbl_setzerop1(resultp1);
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(opnd1p1)) {
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
|
||||
if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
|
||||
/*
|
||||
* invalid since both operands
|
||||
* are infinity
|
||||
*/
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd1p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd1p1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Dbl_is_signalingnan(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(opnd2p1)) {
|
||||
if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
|
||||
/*
|
||||
* return zero
|
||||
*/
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* check for division by zero
|
||||
*/
|
||||
if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
|
||||
if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
|
||||
/* invalid since both operands are zero */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
if (Is_divisionbyzerotrap_enabled())
|
||||
return(DIVISIONBYZEROEXCEPTION);
|
||||
Set_divisionbyzeroflag();
|
||||
Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent
|
||||
*/
|
||||
dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Generate mantissa
|
||||
*/
|
||||
if (Dbl_isnotzero_exponent(opnd1p1)) {
|
||||
/* set hidden bit */
|
||||
Dbl_clear_signexponent_set_hidden(opnd1p1);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized, want to normalize */
|
||||
Dbl_clear_signexponent(opnd1p1);
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
|
||||
}
|
||||
/* opnd2 needs to have hidden bit set with msb in hidden bit */
|
||||
if (Dbl_isnotzero_exponent(opnd2p1)) {
|
||||
Dbl_clear_signexponent_set_hidden(opnd2p1);
|
||||
}
|
||||
else {
|
||||
/* is denormalized; want to normalize */
|
||||
Dbl_clear_signexponent(opnd2p1);
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
|
||||
dest_exponent+=8;
|
||||
Dbl_leftshiftby8(opnd2p1,opnd2p2);
|
||||
}
|
||||
if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
|
||||
dest_exponent+=4;
|
||||
Dbl_leftshiftby4(opnd2p1,opnd2p2);
|
||||
}
|
||||
while (Dbl_iszero_hidden(opnd2p1)) {
|
||||
dest_exponent++;
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Divide the source mantissas */
|
||||
|
||||
/*
|
||||
* A non-restoring divide algorithm is used.
|
||||
*/
|
||||
Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
|
||||
Dbl_setzero(opnd3p1,opnd3p2);
|
||||
for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
if (Dbl_iszero_sign(opnd1p1)) {
|
||||
Dbl_setone_lowmantissap2(opnd3p2);
|
||||
Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
|
||||
}
|
||||
else {
|
||||
Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
|
||||
}
|
||||
}
|
||||
if (count <= DBL_P) {
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
Dbl_setone_lowmantissap2(opnd3p2);
|
||||
Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
|
||||
if (Dbl_iszero_hidden(opnd3p1)) {
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
dest_exponent--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Dbl_iszero_hidden(opnd3p1)) {
|
||||
/* need to get one more bit of result */
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
if (Dbl_iszero_sign(opnd1p1)) {
|
||||
Dbl_setone_lowmantissap2(opnd3p2);
|
||||
Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
|
||||
}
|
||||
else {
|
||||
Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
|
||||
}
|
||||
dest_exponent--;
|
||||
}
|
||||
if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
|
||||
stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
|
||||
}
|
||||
inexact = guardbit | stickybit;
|
||||
|
||||
/*
|
||||
* round result
|
||||
*/
|
||||
if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
|
||||
Dbl_clear_signexponent(opnd3p1);
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1))
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1))
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opnd3p2))) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
}
|
||||
if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
|
||||
}
|
||||
Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (dest_exponent >= DBL_INFINITY_EXPONENT) {
|
||||
/* trap if OVERFLOWTRAP enabled */
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
Set_overflowflag();
|
||||
/* set result to infinity or largest number */
|
||||
Dbl_setoverflow(resultp1,resultp2);
|
||||
inexact = TRUE;
|
||||
}
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
else if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
|
||||
/* Determine if should set underflow flag */
|
||||
is_tiny = TRUE;
|
||||
if (dest_exponent == 0 && inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opnd3p2))) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
stickybit = inexact;
|
||||
Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
|
||||
stickybit,inexact);
|
||||
|
||||
/* return rounded number */
|
||||
if (inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opnd3p2))) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_tiny) Set_underflowflag();
|
||||
}
|
||||
Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
|
||||
}
|
||||
else Dbl_set_exponent(resultp1,dest_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
394
arch/parisc/math-emu/dfmpy.c
Обычный файл
394
arch/parisc/math-emu/dfmpy.c
Обычный файл
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfmpy.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double Precision Floating-point Multiply
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fmpy(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double Precision Floating-point Multiply
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_fmpy(
|
||||
dbl_floating_point *srcptr1,
|
||||
dbl_floating_point *srcptr2,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
|
||||
register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
|
||||
register int dest_exponent, count;
|
||||
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
|
||||
boolean is_tiny;
|
||||
|
||||
Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
|
||||
Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
|
||||
|
||||
/*
|
||||
* set sign bit of result
|
||||
*/
|
||||
if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
|
||||
Dbl_setnegativezerop1(resultp1);
|
||||
else Dbl_setzerop1(resultp1);
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(opnd1p1)) {
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
|
||||
if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
|
||||
/*
|
||||
* invalid since operands are infinity
|
||||
* and zero
|
||||
*/
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd1p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd1p1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Dbl_is_signalingnan(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(opnd2p1)) {
|
||||
if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
|
||||
if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
|
||||
/* invalid since operands are zero & infinity */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(opnd2p1,opnd2p2);
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent
|
||||
*/
|
||||
dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Generate mantissa
|
||||
*/
|
||||
if (Dbl_isnotzero_exponent(opnd1p1)) {
|
||||
/* set hidden bit */
|
||||
Dbl_clear_signexponent_set_hidden(opnd1p1);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized, adjust exponent */
|
||||
Dbl_clear_signexponent(opnd1p1);
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
|
||||
}
|
||||
/* opnd2 needs to have hidden bit set with msb in hidden bit */
|
||||
if (Dbl_isnotzero_exponent(opnd2p1)) {
|
||||
Dbl_clear_signexponent_set_hidden(opnd2p1);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized; want to normalize */
|
||||
Dbl_clear_signexponent(opnd2p1);
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
|
||||
}
|
||||
|
||||
/* Multiply two source mantissas together */
|
||||
|
||||
/* make room for guard bits */
|
||||
Dbl_leftshiftby7(opnd2p1,opnd2p2);
|
||||
Dbl_setzero(opnd3p1,opnd3p2);
|
||||
/*
|
||||
* Four bits at a time are inspected in each loop, and a
|
||||
* simple shift and add multiply algorithm is used.
|
||||
*/
|
||||
for (count=1;count<=DBL_P;count+=4) {
|
||||
stickybit |= Dlow4p2(opnd3p2);
|
||||
Dbl_rightshiftby4(opnd3p1,opnd3p2);
|
||||
if (Dbit28p2(opnd1p2)) {
|
||||
/* Twoword_add should be an ADDC followed by an ADD. */
|
||||
Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29,
|
||||
opnd2p2<<3);
|
||||
}
|
||||
if (Dbit29p2(opnd1p2)) {
|
||||
Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30,
|
||||
opnd2p2<<2);
|
||||
}
|
||||
if (Dbit30p2(opnd1p2)) {
|
||||
Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
|
||||
opnd2p2<<1);
|
||||
}
|
||||
if (Dbit31p2(opnd1p2)) {
|
||||
Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
|
||||
}
|
||||
Dbl_rightshiftby4(opnd1p1,opnd1p2);
|
||||
}
|
||||
if (Dbit3p1(opnd3p1)==0) {
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
}
|
||||
else {
|
||||
/* result mantissa >= 2. */
|
||||
dest_exponent++;
|
||||
}
|
||||
/* check for denormalized result */
|
||||
while (Dbit3p1(opnd3p1)==0) {
|
||||
Dbl_leftshiftby1(opnd3p1,opnd3p2);
|
||||
dest_exponent--;
|
||||
}
|
||||
/*
|
||||
* check for guard, sticky and inexact bits
|
||||
*/
|
||||
stickybit |= Dallp2(opnd3p2) << 25;
|
||||
guardbit = (Dallp2(opnd3p2) << 24) >> 31;
|
||||
inexact = guardbit | stickybit;
|
||||
|
||||
/* align result mantissa */
|
||||
Dbl_rightshiftby8(opnd3p1,opnd3p2);
|
||||
|
||||
/*
|
||||
* round result
|
||||
*/
|
||||
if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
|
||||
Dbl_clear_signexponent(opnd3p1);
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1))
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1))
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit) {
|
||||
if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
}
|
||||
if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
|
||||
}
|
||||
Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (dest_exponent >= DBL_INFINITY_EXPONENT) {
|
||||
/* trap if OVERFLOWTRAP enabled */
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return (OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return (OVERFLOWEXCEPTION);
|
||||
}
|
||||
inexact = TRUE;
|
||||
Set_overflowflag();
|
||||
/* set result to infinity or largest number */
|
||||
Dbl_setoverflow(resultp1,resultp2);
|
||||
}
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
else if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return (UNDERFLOWEXCEPTION);
|
||||
}
|
||||
|
||||
/* Determine if should set underflow flag */
|
||||
is_tiny = TRUE;
|
||||
if (dest_exponent == 0 && inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opnd3p2))) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
if (Dbl_isone_hiddenoverflow(opnd3p1))
|
||||
is_tiny = FALSE;
|
||||
Dbl_decrement(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
stickybit = inexact;
|
||||
Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
|
||||
stickybit,inexact);
|
||||
|
||||
/* return zero or smallest number */
|
||||
if (inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1)) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Dbl_isone_lowmantissap2(opnd3p2))) {
|
||||
Dbl_increment(opnd3p1,opnd3p2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_tiny) Set_underflowflag();
|
||||
}
|
||||
Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
|
||||
}
|
||||
else Dbl_set_exponent(resultp1,dest_exponent);
|
||||
/* check for inexact */
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
297
arch/parisc/math-emu/dfrem.c
Обычный файл
297
arch/parisc/math-emu/dfrem.c
Обычный файл
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfrem.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double Precision Floating-point Remainder
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_frem(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double Precision Floating-point Remainder
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
|
||||
dbl_floating_point * dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
|
||||
register unsigned int resultp1, resultp2;
|
||||
register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
|
||||
register boolean roundup = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
|
||||
Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
|
||||
/* invalid since first operand is infinity */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd1p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd1p1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Dbl_is_signalingnan(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
|
||||
if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
|
||||
/*
|
||||
* return first operand
|
||||
*/
|
||||
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(opnd2p1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(opnd2p1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* check second operand for zero
|
||||
*/
|
||||
if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
|
||||
/* invalid since second operand is zero */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* get sign of result
|
||||
*/
|
||||
resultp1 = opnd1p1;
|
||||
|
||||
/*
|
||||
* check for denormalized operands
|
||||
*/
|
||||
if (opnd1_exponent == 0) {
|
||||
/* check for zero */
|
||||
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
|
||||
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* normalize, then continue */
|
||||
opnd1_exponent = 1;
|
||||
Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
|
||||
}
|
||||
else {
|
||||
Dbl_clear_signexponent_set_hidden(opnd1p1);
|
||||
}
|
||||
if (opnd2_exponent == 0) {
|
||||
/* normalize, then continue */
|
||||
opnd2_exponent = 1;
|
||||
Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
|
||||
}
|
||||
else {
|
||||
Dbl_clear_signexponent_set_hidden(opnd2p1);
|
||||
}
|
||||
|
||||
/* find result exponent and divide step loop count */
|
||||
dest_exponent = opnd2_exponent - 1;
|
||||
stepcount = opnd1_exponent - opnd2_exponent;
|
||||
|
||||
/*
|
||||
* check for opnd1/opnd2 < 1
|
||||
*/
|
||||
if (stepcount < 0) {
|
||||
/*
|
||||
* check for opnd1/opnd2 > 1/2
|
||||
*
|
||||
* In this case n will round to 1, so
|
||||
* r = opnd1 - opnd2
|
||||
*/
|
||||
if (stepcount == -1 &&
|
||||
Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
|
||||
/* set sign */
|
||||
Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
|
||||
/* align opnd2 with opnd1 */
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
|
||||
opnd2p1,opnd2p2);
|
||||
/* now normalize */
|
||||
while (Dbl_iszero_hidden(opnd2p1)) {
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
dest_exponent--;
|
||||
}
|
||||
Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
|
||||
goto testforunderflow;
|
||||
}
|
||||
/*
|
||||
* opnd1/opnd2 <= 1/2
|
||||
*
|
||||
* In this case n will round to zero, so
|
||||
* r = opnd1
|
||||
*/
|
||||
Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
|
||||
dest_exponent = opnd1_exponent;
|
||||
goto testforunderflow;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*
|
||||
* Do iterative subtract until remainder is less than operand 2.
|
||||
*/
|
||||
while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
|
||||
if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
|
||||
Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
|
||||
}
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
}
|
||||
/*
|
||||
* Do last subtract, then determine which way to round if remainder
|
||||
* is exactly 1/2 of opnd2
|
||||
*/
|
||||
if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
|
||||
Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
|
||||
roundup = TRUE;
|
||||
}
|
||||
if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
|
||||
/* division is exact, remainder is zero */
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for cases where opnd1/opnd2 < n
|
||||
*
|
||||
* In this case the result's sign will be opposite that of
|
||||
* opnd1. The mantissa also needs some correction.
|
||||
*/
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
|
||||
Dbl_invert_sign(resultp1);
|
||||
Dbl_leftshiftby1(opnd2p1,opnd2p2);
|
||||
Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
|
||||
}
|
||||
/* check for remainder being exactly 1/2 of opnd2 */
|
||||
else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
|
||||
Dbl_invert_sign(resultp1);
|
||||
}
|
||||
|
||||
/* normalize result's mantissa */
|
||||
while (Dbl_iszero_hidden(opnd1p1)) {
|
||||
dest_exponent--;
|
||||
Dbl_leftshiftby1(opnd1p1,opnd1p2);
|
||||
}
|
||||
Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
|
||||
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
testforunderflow:
|
||||
if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
|
||||
/* frem is always exact */
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
if (dest_exponent >= (1 - DBL_P)) {
|
||||
Dbl_rightshift_exponentmantissa(resultp1,resultp2,
|
||||
1-dest_exponent);
|
||||
}
|
||||
else {
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
else Dbl_set_exponent(resultp1,dest_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
195
arch/parisc/math-emu/dfsqrt.c
Обычный файл
195
arch/parisc/math-emu/dfsqrt.c
Обычный файл
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double Floating-point Square Root
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fsqrt(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double Floating-point Square Root
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
unsigned int
|
||||
dbl_fsqrt(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, resultp1, resultp2;
|
||||
register unsigned int newbitp1, newbitp2, sump1, sump2;
|
||||
register int src_exponent;
|
||||
register boolean guardbit = FALSE, even_exponent;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
/*
|
||||
* check source operand for NaN or infinity
|
||||
*/
|
||||
if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* is signaling NaN?
|
||||
*/
|
||||
if (Dbl_isone_signaling(srcp1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(srcp1);
|
||||
}
|
||||
/*
|
||||
* Return quiet NaN or positive infinity.
|
||||
* Fall thru to negative test if negative infinity.
|
||||
*/
|
||||
if (Dbl_iszero_sign(srcp1) ||
|
||||
Dbl_isnotzero_mantissa(srcp1,srcp2)) {
|
||||
Dbl_copytoptr(srcp1,srcp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check for zero source operand
|
||||
*/
|
||||
if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
|
||||
Dbl_copytoptr(srcp1,srcp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* check for negative source operand
|
||||
*/
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(srcp1,srcp2);
|
||||
Dbl_copytoptr(srcp1,srcp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent > 0) {
|
||||
even_exponent = Dbl_hidden(srcp1);
|
||||
Dbl_clear_signexponent_set_hidden(srcp1);
|
||||
}
|
||||
else {
|
||||
/* normalize operand */
|
||||
Dbl_clear_signexponent(srcp1);
|
||||
src_exponent++;
|
||||
Dbl_normalize(srcp1,srcp2,src_exponent);
|
||||
even_exponent = src_exponent & 1;
|
||||
}
|
||||
if (even_exponent) {
|
||||
/* exponent is even */
|
||||
/* Add comment here. Explain why odd exponent needs correction */
|
||||
Dbl_leftshiftby1(srcp1,srcp2);
|
||||
}
|
||||
/*
|
||||
* Add comment here. Explain following algorithm.
|
||||
*
|
||||
* Trust me, it works.
|
||||
*
|
||||
*/
|
||||
Dbl_setzero(resultp1,resultp2);
|
||||
Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
|
||||
Dbl_setzero_mantissap2(newbitp2);
|
||||
while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
|
||||
Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
|
||||
if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
|
||||
Dbl_leftshiftby1(newbitp1,newbitp2);
|
||||
/* update result */
|
||||
Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
|
||||
resultp1,resultp2);
|
||||
Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
|
||||
Dbl_rightshiftby2(newbitp1,newbitp2);
|
||||
}
|
||||
else {
|
||||
Dbl_rightshiftby1(newbitp1,newbitp2);
|
||||
}
|
||||
Dbl_leftshiftby1(srcp1,srcp2);
|
||||
}
|
||||
/* correct exponent for pre-shift */
|
||||
if (even_exponent) {
|
||||
Dbl_rightshiftby1(resultp1,resultp2);
|
||||
}
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero(srcp1,srcp2)) {
|
||||
if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
guardbit = Dbl_lowmantissap2(resultp2);
|
||||
Dbl_rightshiftby1(resultp1,resultp2);
|
||||
|
||||
/* now round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
/* stickybit is always true, so guardbit
|
||||
* is enough to determine rounding */
|
||||
if (guardbit) {
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* increment result exponent by 1 if mantissa overflowed */
|
||||
if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;
|
||||
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
Dbl_set_exponent(resultp1,
|
||||
((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
else {
|
||||
Dbl_rightshiftby1(resultp1,resultp2);
|
||||
}
|
||||
Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
526
arch/parisc/math-emu/dfsub.c
Обычный файл
526
arch/parisc/math-emu/dfsub.c
Обычный файл
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/dfsub.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Double_subtract: subtract two double precision values.
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_fsub(leftptr, rightptr, dstptr, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "dbl_float.h"
|
||||
|
||||
/*
|
||||
* Double_subtract: subtract two double precision values.
|
||||
*/
|
||||
int
|
||||
dbl_fsub(
|
||||
dbl_floating_point *leftptr,
|
||||
dbl_floating_point *rightptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int signless_upper_left, signless_upper_right, save;
|
||||
register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
|
||||
register unsigned int resultp1 = 0, resultp2 = 0;
|
||||
|
||||
register int result_exponent, right_exponent, diff_exponent;
|
||||
register int sign_save, jumpsize;
|
||||
register boolean inexact = FALSE, underflowtrap;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
Dbl_copyfromptr(leftptr,leftp1,leftp2);
|
||||
Dbl_copyfromptr(rightptr,rightp1,rightp2);
|
||||
|
||||
/* A zero "save" helps discover equal operands (for later), *
|
||||
* and is used in swapping operands (if needed). */
|
||||
Dbl_xortointp1(leftp1,rightp1,/*to*/save);
|
||||
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
|
||||
{
|
||||
if (Dbl_iszero_mantissa(leftp1,leftp2))
|
||||
{
|
||||
if (Dbl_isnotnan(rightp1,rightp2))
|
||||
{
|
||||
if (Dbl_isinfinity(rightp1,rightp2) && save==0)
|
||||
{
|
||||
/*
|
||||
* invalid since operands are same signed infinity's
|
||||
*/
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Dbl_makequietnan(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(leftp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(leftp1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Dbl_is_signalingnan(rightp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(rightp1);
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
} /* End left NaN or Infinity processing */
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Dbl_isinfinity_exponent(rightp1))
|
||||
{
|
||||
if (Dbl_iszero_mantissa(rightp1,rightp2))
|
||||
{
|
||||
/* return infinity */
|
||||
Dbl_invert_sign(rightp1);
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(rightp1))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(rightp1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
Dbl_copytoptr(rightp1,rightp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
} /* End right NaN or Infinity processing */
|
||||
|
||||
/* Invariant: Must be dealing with finite numbers */
|
||||
|
||||
/* Compare operands by removing the sign */
|
||||
Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
|
||||
Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
|
||||
|
||||
/* sign difference selects add or sub operation. */
|
||||
if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
|
||||
{
|
||||
/* Set the left operand to the larger one by XOR swap *
|
||||
* First finish the first word using "save" */
|
||||
Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
|
||||
Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
|
||||
Dbl_swap_lower(leftp2,rightp2);
|
||||
result_exponent = Dbl_exponent(leftp1);
|
||||
Dbl_invert_sign(leftp1);
|
||||
}
|
||||
/* Invariant: left is not smaller than right. */
|
||||
|
||||
if((right_exponent = Dbl_exponent(rightp1)) == 0)
|
||||
{
|
||||
/* Denormalized operands. First look for zeroes */
|
||||
if(Dbl_iszero_mantissa(rightp1,rightp2))
|
||||
{
|
||||
/* right is zero */
|
||||
if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
|
||||
{
|
||||
/* Both operands are zeros */
|
||||
Dbl_invert_sign(rightp1);
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Dbl_or_signs(leftp1,/*with*/rightp1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_and_signs(leftp1,/*with*/rightp1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left is not a zero and must be the result. Trapped
|
||||
* underflows are signaled if left is denormalized. Result
|
||||
* is always exact. */
|
||||
if( (result_exponent == 0) && Is_underflowtrap_enabled() )
|
||||
{
|
||||
/* need to normalize results mantissa */
|
||||
sign_save = Dbl_signextendedsign(leftp1);
|
||||
Dbl_leftshiftby1(leftp1,leftp2);
|
||||
Dbl_normalize(leftp1,leftp2,result_exponent);
|
||||
Dbl_set_sign(leftp1,/*using*/sign_save);
|
||||
Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
}
|
||||
Dbl_copytoptr(leftp1,leftp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/* Neither are zeroes */
|
||||
Dbl_clear_sign(rightp1); /* Exponent is already cleared */
|
||||
if(result_exponent == 0 )
|
||||
{
|
||||
/* Both operands are denormalized. The result must be exact
|
||||
* and is simply calculated. A sum could become normalized and a
|
||||
* difference could cancel to a true zero. */
|
||||
if( (/*signed*/int) save >= 0 )
|
||||
{
|
||||
Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
|
||||
/*into*/resultp1,resultp2);
|
||||
if(Dbl_iszero_mantissa(resultp1,resultp2))
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Dbl_setone_sign(resultp1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_setzero_sign(resultp1);
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_addition(leftp1,leftp2,rightp1,rightp2,
|
||||
/*into*/resultp1,resultp2);
|
||||
if(Dbl_isone_hidden(resultp1))
|
||||
{
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
/* need to normalize result */
|
||||
sign_save = Dbl_signextendedsign(resultp1);
|
||||
Dbl_leftshiftby1(resultp1,resultp2);
|
||||
Dbl_normalize(resultp1,resultp2,result_exponent);
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
right_exponent = 1; /* Set exponent to reflect different bias
|
||||
* with denomalized numbers. */
|
||||
}
|
||||
else
|
||||
{
|
||||
Dbl_clear_signexponent_set_hidden(rightp1);
|
||||
}
|
||||
Dbl_clear_exponent_set_hidden(leftp1);
|
||||
diff_exponent = result_exponent - right_exponent;
|
||||
|
||||
/*
|
||||
* Special case alignment of operands that would force alignment
|
||||
* beyond the extent of the extension. A further optimization
|
||||
* could special case this but only reduces the path length for this
|
||||
* infrequent case.
|
||||
*/
|
||||
if(diff_exponent > DBL_THRESHOLD)
|
||||
{
|
||||
diff_exponent = DBL_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Align right operand by shifting to right */
|
||||
Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
|
||||
/*and lower to*/extent);
|
||||
|
||||
/* Treat sum and difference of the operands separately. */
|
||||
if( (/*signed*/int) save >= 0 )
|
||||
{
|
||||
/*
|
||||
* Difference of the two operands. Their can be no overflow. A
|
||||
* borrow can occur out of the hidden bit and force a post
|
||||
* normalization phase.
|
||||
*/
|
||||
Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
|
||||
/*with*/extent,/*into*/resultp1,resultp2);
|
||||
if(Dbl_iszero_hidden(resultp1))
|
||||
{
|
||||
/* Handle normalization */
|
||||
/* A straight foward algorithm would now shift the result
|
||||
* and extension left until the hidden bit becomes one. Not
|
||||
* all of the extension bits need participate in the shift.
|
||||
* Only the two most significant bits (round and guard) are
|
||||
* needed. If only a single shift is needed then the guard
|
||||
* bit becomes a significant low order bit and the extension
|
||||
* must participate in the rounding. If more than a single
|
||||
* shift is needed, then all bits to the right of the guard
|
||||
* bit are zeros, and the guard bit may or may not be zero. */
|
||||
sign_save = Dbl_signextendedsign(resultp1);
|
||||
Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
|
||||
|
||||
/* Need to check for a zero result. The sign and exponent
|
||||
* fields have already been zeroed. The more efficient test
|
||||
* of the full object can be used.
|
||||
*/
|
||||
if(Dbl_iszero(resultp1,resultp2))
|
||||
/* Must have been "x-x" or "x+(-x)". */
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
result_exponent--;
|
||||
/* Look to see if normalization is finished. */
|
||||
if(Dbl_isone_hidden(resultp1))
|
||||
{
|
||||
if(result_exponent==0)
|
||||
{
|
||||
/* Denormalized, exponent should be zero. Left operand *
|
||||
* was normalized, so extent (guard, round) was zero */
|
||||
goto underflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No further normalization is needed. */
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Ext_leftshiftby1(extent);
|
||||
goto round;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for denormalized, exponent should be zero. Left *
|
||||
* operand was normalized, so extent (guard, round) was zero */
|
||||
if(!(underflowtrap = Is_underflowtrap_enabled()) &&
|
||||
result_exponent==0) goto underflow;
|
||||
|
||||
/* Shift extension to complete one bit of normalization and
|
||||
* update exponent. */
|
||||
Ext_leftshiftby1(extent);
|
||||
|
||||
/* Discover first one bit to determine shift amount. Use a
|
||||
* modified binary search. We have already shifted the result
|
||||
* one position right and still not found a one so the remainder
|
||||
* of the extension must be zero and simplifies rounding. */
|
||||
/* Scan bytes */
|
||||
while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
|
||||
{
|
||||
Dbl_leftshiftby8(resultp1,resultp2);
|
||||
if((result_exponent -= 8) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Now narrow it down to the nibble */
|
||||
if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
|
||||
{
|
||||
/* The lower nibble contains the normalizing one */
|
||||
Dbl_leftshiftby4(resultp1,resultp2);
|
||||
if((result_exponent -= 4) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Select case were first bit is set (already normalized)
|
||||
* otherwise select the proper shift. */
|
||||
if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
|
||||
{
|
||||
/* Already normalized */
|
||||
if(result_exponent <= 0) goto underflow;
|
||||
Dbl_set_sign(resultp1,/*using*/sign_save);
|
||||
Dbl_set_exponent(resultp1,/*using*/result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_sethigh4bits(resultp1,/*using*/sign_save);
|
||||
switch(jumpsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Dbl_leftshiftby3(resultp1,resultp2);
|
||||
result_exponent -= 3;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
Dbl_leftshiftby2(resultp1,resultp2);
|
||||
result_exponent -= 2;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
Dbl_leftshiftby1(resultp1,resultp2);
|
||||
result_exponent -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result_exponent > 0)
|
||||
{
|
||||
Dbl_set_exponent(resultp1,/*using*/result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION); /* Sign bit is already set */
|
||||
}
|
||||
/* Fixup potential underflows */
|
||||
underflow:
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
Dbl_set_sign(resultp1,sign_save);
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Since we cannot get an inexact denormalized result,
|
||||
* we can now return.
|
||||
*/
|
||||
Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
|
||||
Dbl_clear_signexponent(resultp1);
|
||||
Dbl_set_sign(resultp1,sign_save);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
} /* end if(hidden...)... */
|
||||
/* Fall through and round */
|
||||
} /* end if(save >= 0)... */
|
||||
else
|
||||
{
|
||||
/* Subtract magnitudes */
|
||||
Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
|
||||
if(Dbl_isone_hiddenoverflow(resultp1))
|
||||
{
|
||||
/* Prenormalization required. */
|
||||
Dbl_rightshiftby1_withextent(resultp2,extent,extent);
|
||||
Dbl_arithrightshiftby1(resultp1,resultp2);
|
||||
result_exponent++;
|
||||
} /* end if hiddenoverflow... */
|
||||
} /* end else ...subtract magnitudes... */
|
||||
|
||||
/* Round the result. If the extension is all zeros,then the result is
|
||||
* exact. Otherwise round in the correct direction. No underflow is
|
||||
* possible. If a postnormalization is necessary, then the mantissa is
|
||||
* all zeros so no shift is needed. */
|
||||
round:
|
||||
if(Ext_isnotzero(extent))
|
||||
{
|
||||
inexact = TRUE;
|
||||
switch(Rounding_mode())
|
||||
{
|
||||
case ROUNDNEAREST: /* The default. */
|
||||
if(Ext_isone_sign(extent))
|
||||
{
|
||||
/* at least 1/2 ulp */
|
||||
if(Ext_isnotzero_lower(extent) ||
|
||||
Dbl_isone_lowmantissap2(resultp2))
|
||||
{
|
||||
/* either exactly half way and odd or more than 1/2ulp */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDPLUS:
|
||||
if(Dbl_iszero_sign(resultp1))
|
||||
{
|
||||
/* Round up positive results */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDMINUS:
|
||||
if(Dbl_isone_sign(resultp1))
|
||||
{
|
||||
/* Round down negative results */
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
|
||||
case ROUNDZERO:;
|
||||
/* truncate is simple */
|
||||
} /* end switch... */
|
||||
if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
|
||||
}
|
||||
if(result_exponent == DBL_INFINITY_EXPONENT)
|
||||
{
|
||||
/* Overflow */
|
||||
if(Is_overflowtrap_enabled())
|
||||
{
|
||||
Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
inexact = TRUE;
|
||||
Set_overflowflag();
|
||||
Dbl_setoverflow(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
else Dbl_set_exponent(resultp1,result_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if(inexact)
|
||||
if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(NOEXCEPTION);
|
||||
}
|
128
arch/parisc/math-emu/driver.c
Обычный файл
128
arch/parisc/math-emu/driver.c
Обычный файл
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* linux/arch/math-emu/driver.c.c
|
||||
*
|
||||
* decodes and dispatches unimplemented FPU instructions
|
||||
*
|
||||
* Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
|
||||
* Copyright (C) 2001 Hewlett-Packard <bame@debian.org>
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include "float.h"
|
||||
#include "math-emu.h"
|
||||
|
||||
|
||||
#define fptpos 31
|
||||
#define fpr1pos 10
|
||||
#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
|
||||
|
||||
#define FPUDEBUG 0
|
||||
|
||||
/* Format of the floating-point exception registers. */
|
||||
struct exc_reg {
|
||||
unsigned int exception : 6;
|
||||
unsigned int ei : 26;
|
||||
};
|
||||
|
||||
/* Macros for grabbing bits of the instruction format from the 'ei'
|
||||
field above. */
|
||||
/* Major opcode 0c and 0e */
|
||||
#define FP0CE_UID(i) (((i) >> 6) & 3)
|
||||
#define FP0CE_CLASS(i) (((i) >> 9) & 3)
|
||||
#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
|
||||
#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
|
||||
#define FP0C_FORMAT(i) (((i) >> 11) & 3)
|
||||
#define FP0E_FORMAT(i) (((i) >> 11) & 1)
|
||||
|
||||
/* Major opcode 0c, uid 2 (performance monitoring) */
|
||||
#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
|
||||
|
||||
/* Major opcode 2e (fused operations). */
|
||||
#define FP2E_SUBOP(i) (((i) >> 5) & 1)
|
||||
#define FP2E_FORMAT(i) (((i) >> 11) & 1)
|
||||
|
||||
/* Major opcode 26 (FMPYSUB) */
|
||||
/* Major opcode 06 (FMPYADD) */
|
||||
#define FPx6_FORMAT(i) ((i) & 0x1f)
|
||||
|
||||
/* Flags and enable bits of the status word. */
|
||||
#define FPSW_FLAGS(w) ((w) >> 27)
|
||||
#define FPSW_ENABLE(w) ((w) & 0x1f)
|
||||
#define FPSW_V (1<<4)
|
||||
#define FPSW_Z (1<<3)
|
||||
#define FPSW_O (1<<2)
|
||||
#define FPSW_U (1<<1)
|
||||
#define FPSW_I (1<<0)
|
||||
|
||||
/* Handle a floating point exception. Return zero if the faulting
|
||||
instruction can be completed successfully. */
|
||||
int
|
||||
handle_fpe(struct pt_regs *regs)
|
||||
{
|
||||
extern void printbinary(unsigned long x, int nbits);
|
||||
struct siginfo si;
|
||||
unsigned int orig_sw, sw;
|
||||
int signalcode;
|
||||
/* need an intermediate copy of float regs because FPU emulation
|
||||
* code expects an artificial last entry which contains zero
|
||||
*
|
||||
* also, the passed in fr registers contain one word that defines
|
||||
* the fpu type. the fpu type information is constructed
|
||||
* inside the emulation code
|
||||
*/
|
||||
__u64 frcopy[36];
|
||||
|
||||
memcpy(frcopy, regs->fr, sizeof regs->fr);
|
||||
frcopy[32] = 0;
|
||||
|
||||
memcpy(&orig_sw, frcopy, sizeof(orig_sw));
|
||||
|
||||
if (FPUDEBUG) {
|
||||
printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n ");
|
||||
printbinary(orig_sw, 32);
|
||||
printk(KERN_DEBUG "\n");
|
||||
}
|
||||
|
||||
signalcode = decode_fpu(frcopy, 0x666);
|
||||
|
||||
/* Status word = FR0L. */
|
||||
memcpy(&sw, frcopy, sizeof(sw));
|
||||
if (FPUDEBUG) {
|
||||
printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n",
|
||||
signalcode >> 24, signalcode & 0xffffff);
|
||||
printbinary(sw, 32);
|
||||
printk(KERN_DEBUG "\n");
|
||||
}
|
||||
|
||||
memcpy(regs->fr, frcopy, sizeof regs->fr);
|
||||
if (signalcode != 0) {
|
||||
si.si_signo = signalcode >> 24;
|
||||
si.si_errno = 0;
|
||||
si.si_code = signalcode & 0xffffff;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(si.si_signo, &si, current);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return signalcode ? -1 : 0;
|
||||
}
|
309
arch/parisc/math-emu/fcnvff.c
Обычный файл
309
arch/parisc/math-emu/fcnvff.c
Обычный файл
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvff.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Floating-point to Double Floating-point
|
||||
* Double Floating-point to Single Floating-point
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/*
|
||||
* Single Floating-point to Double Floating-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_dbl_fcnvff(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, resultp1, resultp2;
|
||||
register int src_exponent;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src);
|
||||
Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
|
||||
/*
|
||||
* Test for NaN or infinity
|
||||
*/
|
||||
if (src_exponent == SGL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* determine if NaN or infinity
|
||||
*/
|
||||
if (Sgl_iszero_mantissa(src)) {
|
||||
/*
|
||||
* is infinity; want to return double infinity
|
||||
*/
|
||||
Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(src)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
else {
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(src);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* NaN is quiet, return as double NaN
|
||||
*/
|
||||
Dbl_setinfinity_exponent(resultp1);
|
||||
Sgl_to_dbl_mantissa(src,resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Test for zero or denormalized
|
||||
*/
|
||||
if (src_exponent == 0) {
|
||||
/*
|
||||
* determine if zero or denormalized
|
||||
*/
|
||||
if (Sgl_isnotzero_mantissa(src)) {
|
||||
/*
|
||||
* is denormalized; want to normalize
|
||||
*/
|
||||
Sgl_clear_signexponent(src);
|
||||
Sgl_leftshiftby1(src);
|
||||
Sgl_normalize(src,src_exponent);
|
||||
Sgl_to_dbl_exponent(src_exponent,resultp1);
|
||||
Sgl_to_dbl_mantissa(src,resultp1,resultp2);
|
||||
}
|
||||
else {
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* No special cases, just complete the conversion
|
||||
*/
|
||||
Sgl_to_dbl_exponent(src_exponent, resultp1);
|
||||
Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Single Floating-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_sgl_fcnvff(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, result;
|
||||
register int src_exponent, dest_exponent, dest_mantissa;
|
||||
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
|
||||
register boolean lsb_odd = FALSE;
|
||||
boolean is_tiny;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1);
|
||||
Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
|
||||
/*
|
||||
* Test for NaN or infinity
|
||||
*/
|
||||
if (src_exponent == DBL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* determine if NaN or infinity
|
||||
*/
|
||||
if (Dbl_iszero_mantissa(srcp1,srcp2)) {
|
||||
/*
|
||||
* is infinity; want to return single infinity
|
||||
*/
|
||||
Sgl_setinfinity_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Dbl_isone_signaling(srcp1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
else {
|
||||
Set_invalidflag();
|
||||
/* make NaN quiet */
|
||||
Dbl_set_quiet(srcp1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* NaN is quiet, return as single NaN
|
||||
*/
|
||||
Sgl_setinfinity_exponent(result);
|
||||
Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
|
||||
if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
Dbl_to_sgl_exponent(src_exponent,dest_exponent);
|
||||
if (dest_exponent > 0) {
|
||||
Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
|
||||
stickybit,lsb_odd);
|
||||
}
|
||||
else {
|
||||
if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
|
||||
guardbit,stickybit,lsb_odd);
|
||||
}
|
||||
else {
|
||||
/* compute result, determine inexact info,
|
||||
* and set Underflowflag if appropriate
|
||||
*/
|
||||
Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
|
||||
dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
|
||||
is_tiny);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now round result if not exact
|
||||
*/
|
||||
if (inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result)) dest_mantissa++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result)) dest_mantissa++;
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit) {
|
||||
if (stickybit || lsb_odd) dest_mantissa++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Sgl_set_exponentmantissa(result,dest_mantissa);
|
||||
|
||||
/*
|
||||
* check for mantissa overflow after rounding
|
||||
*/
|
||||
if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
|
||||
Sgl_isone_hidden(result)) dest_exponent++;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (dest_exponent >= SGL_INFINITY_EXPONENT) {
|
||||
/* trap if OVERFLOWTRAP enabled */
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
/*
|
||||
* Check for gross overflow
|
||||
*/
|
||||
if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
|
||||
return(UNIMPLEMENTEDEXCEPTION);
|
||||
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
Set_overflowflag();
|
||||
inexact = TRUE;
|
||||
/* set result to infinity or largest number */
|
||||
Sgl_setoverflow(result);
|
||||
}
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
else if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Check for gross underflow
|
||||
*/
|
||||
if (dest_exponent <= -(SGL_WRAP))
|
||||
return(UNIMPLEMENTEDEXCEPTION);
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,unfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* result is denormalized or signed zero
|
||||
*/
|
||||
if (inexact && is_tiny) Set_underflowflag();
|
||||
|
||||
}
|
||||
else Sgl_set_exponent(result,dest_exponent);
|
||||
*dstptr = result;
|
||||
/*
|
||||
* Trap if inexact trap is enabled
|
||||
*/
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(NOEXCEPTION);
|
||||
}
|
536
arch/parisc/math-emu/fcnvfu.c
Обычный файл
536
arch/parisc/math-emu/fcnvfu.c
Обычный файл
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Floating-point to Unsigned Fixed-point Converts
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/************************************************************************
|
||||
* Floating-point to Unsigned Fixed-point Converts *
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Single Floating-point to Single Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_sgl_fcnvfu(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
unsigned int *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, result;
|
||||
register int src_exponent;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP + 1) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_clear_signexponent_set_hidden(src);
|
||||
Suint_from_sgl_mantissa(src,src_exponent,result);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
result++;
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Sgl_isone_roundbit(src,src_exponent) &&
|
||||
(Sgl_isone_stickybit(src,src_exponent) ||
|
||||
(result & 1))) {
|
||||
result++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
result++;
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1 &&
|
||||
Sgl_isnotzero_mantissa(src)) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
else result++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dstptr = result;
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Floating-point to Double Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_dbl_fcnvfu(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_unsigned *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src_exponent;
|
||||
register unsigned int src, resultp1, resultp2;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP + 1) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
} else {
|
||||
resultp1 = resultp2 = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_clear_signexponent_set_hidden(src);
|
||||
Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Duint_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Sgl_isone_roundbit(src,src_exponent) &&
|
||||
(Sgl_isone_stickybit(src,src_exponent) ||
|
||||
Duint_isone_lowp2(resultp2))) {
|
||||
Duint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Duint_setzero(resultp1,resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
Duint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1 &&
|
||||
Sgl_isnotzero_mantissa(src)) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = 0;
|
||||
resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
else Duint_increment(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Single Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
|
||||
unsigned int *dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, result;
|
||||
register int src_exponent;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP + 1) {
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_clear_signexponent_set_hidden(srcp1);
|
||||
Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
result++;
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
|
||||
(Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
|
||||
result&1))
|
||||
result++;
|
||||
break;
|
||||
}
|
||||
/* check for overflow */
|
||||
if (result == 0) {
|
||||
result = 0xffffffff;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) result++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1 &&
|
||||
Dbl_isnotzero_mantissa(srcp1,srcp2))
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
else result++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dstptr = result;
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Double Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
|
||||
dbl_unsigned * dstptr, unsigned int *status)
|
||||
{
|
||||
register int src_exponent;
|
||||
register unsigned int srcp1, srcp2, resultp1, resultp2;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP + 1) {
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
} else {
|
||||
resultp1 = resultp2 = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_clear_signexponent_set_hidden(srcp1);
|
||||
Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
|
||||
resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Duint_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
|
||||
if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
|
||||
Duint_isone_lowp2(resultp2))
|
||||
Duint_increment(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Duint_setzero(resultp1,resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Duint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1 &&
|
||||
Dbl_isnotzero_mantissa(srcp1,srcp2))
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Duint_increment(resultp1,resultp2);
|
||||
} else {
|
||||
resultp1 = 0;
|
||||
resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
inexact = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
332
arch/parisc/math-emu/fcnvfut.c
Обычный файл
332
arch/parisc/math-emu/fcnvfut.c
Обычный файл
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Floating-point to Unsigned Fixed-point Converts with Truncation
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/************************************************************************
|
||||
* Floating-point to Unsigned Fixed-point Converts with Truncation *
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Convert single floating-point to single fixed-point format
|
||||
* with truncated result
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
|
||||
unsigned int *dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int src, result;
|
||||
register int src_exponent;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP + 1) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Sgl_isone_sign(src)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_clear_signexponent_set_hidden(src);
|
||||
Suint_from_sgl_mantissa(src,src_exponent,result);
|
||||
*dstptr = result;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dstptr = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Floating-point to Double Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
|
||||
dbl_unsigned * dstptr, unsigned int *status)
|
||||
{
|
||||
register int src_exponent;
|
||||
register unsigned int src, resultp1, resultp2;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP + 1) {
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
} else {
|
||||
resultp1 = resultp2 = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Sgl_isone_sign(src)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_clear_signexponent_set_hidden(src);
|
||||
Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Duint_setzero(resultp1,resultp2);
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Single Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
|
||||
unsigned int *dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, result;
|
||||
register int src_exponent;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP + 1) {
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
result = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_clear_signexponent_set_hidden(srcp1);
|
||||
Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
|
||||
*dstptr = result;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dstptr = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Double Unsigned Fixed
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
|
||||
dbl_unsigned * dstptr, unsigned int *status)
|
||||
{
|
||||
register int src_exponent;
|
||||
register unsigned int srcp1, srcp2, resultp1, resultp2;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP + 1) {
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
} else {
|
||||
resultp1 = resultp2 = 0xffffffff;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
/*
|
||||
* Check sign.
|
||||
* If negative, trap unimplemented.
|
||||
*/
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
resultp1 = resultp2 = 0;
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dbl_clear_signexponent_set_hidden(srcp1);
|
||||
Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
|
||||
resultp1,resultp2);
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Duint_setzero(resultp1,resultp2);
|
||||
Duint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
501
arch/parisc/math-emu/fcnvfx.c
Обычный файл
501
arch/parisc/math-emu/fcnvfx.c
Обычный файл
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Floating-point to Single Fixed-point
|
||||
* Single Floating-point to Double Fixed-point
|
||||
* Double Floating-point to Single Fixed-point
|
||||
* Double Floating-point to Double Fixed-point
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/*
|
||||
* Single Floating-point to Single Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_sgl_fcnvfx(
|
||||
sgl_floating_point *srcptr,
|
||||
sgl_floating_point *nullptr,
|
||||
int *dstptr,
|
||||
sgl_floating_point *status)
|
||||
{
|
||||
register unsigned int src, temp;
|
||||
register int src_exponent, result;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
|
||||
Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
|
||||
if (Sgl_iszero_sign(src)) result = 0x7fffffff;
|
||||
else result = 0x80000000;
|
||||
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
temp = src;
|
||||
Sgl_clear_signexponent_set_hidden(temp);
|
||||
Int_from_sgl_mantissa(temp,src_exponent);
|
||||
if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
|
||||
else result = Sgl_all(temp);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_fix(src,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) result++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) result--;
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Sgl_isone_roundbit(src,src_exponent)) {
|
||||
if (Sgl_isone_stickybit(src,src_exponent)
|
||||
|| (Sgl_isone_lowmantissa(temp)))
|
||||
if (Sgl_iszero_sign(src)) result++;
|
||||
else result--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) result++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) result--;
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Sgl_isnotzero_mantissa(src))
|
||||
if (Sgl_iszero_sign(src)) result++;
|
||||
else result--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dstptr = result;
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Floating-point to Double Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_dbl_fcnvfx(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_integer *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src_exponent, resultp1;
|
||||
register unsigned int src, temp, resultp2;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
|
||||
Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
resultp1 = 0x7fffffff;
|
||||
resultp2 = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
resultp1 = 0x80000000;
|
||||
resultp2 = 0;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dint_set_minint(resultp1,resultp2);
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
temp = src;
|
||||
Sgl_clear_signexponent_set_hidden(temp);
|
||||
Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
|
||||
if (Sgl_isone_sign(src)) {
|
||||
Dint_setone_sign(resultp1,resultp2);
|
||||
}
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_fix(src,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Sgl_isone_roundbit(src,src_exponent))
|
||||
if (Sgl_isone_stickybit(src,src_exponent) ||
|
||||
(Dint_isone_lowp2(resultp2)))
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
else {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Dint_setzero(resultp1,resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Sgl_isnotzero_mantissa(src))
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
else {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Single Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_sgl_fcnvfx(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
int *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1,srcp2, tempp1,tempp2;
|
||||
register int src_exponent, result;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
|
||||
if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
|
||||
else result = 0x80000000;
|
||||
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
tempp1 = srcp1;
|
||||
tempp2 = srcp2;
|
||||
Dbl_clear_signexponent_set_hidden(tempp1);
|
||||
Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
|
||||
if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
|
||||
result = -Dbl_allp1(tempp1);
|
||||
else result = Dbl_allp1(tempp1);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) result++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) result--;
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
|
||||
if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
|
||||
(Dbl_isone_lowmantissap1(tempp1)))
|
||||
if (Dbl_iszero_sign(srcp1)) result++;
|
||||
else result--;
|
||||
}
|
||||
/* check for overflow */
|
||||
if ((Dbl_iszero_sign(srcp1) && result < 0) ||
|
||||
(Dbl_isone_sign(srcp1) && result > 0)) {
|
||||
|
||||
if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
|
||||
else result = 0x80000000;
|
||||
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) result++;
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) result--;
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Dbl_isnotzero_mantissa(srcp1,srcp2))
|
||||
if (Dbl_iszero_sign(srcp1)) result++;
|
||||
else result--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dstptr = result;
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Double Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_dbl_fcnvfx(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_integer *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src_exponent, resultp1;
|
||||
register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
|
||||
Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
resultp1 = 0x7fffffff;
|
||||
resultp2 = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
resultp1 = 0x80000000;
|
||||
resultp2 = 0;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
tempp1 = srcp1;
|
||||
tempp2 = srcp2;
|
||||
Dbl_clear_signexponent_set_hidden(tempp1);
|
||||
Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
|
||||
resultp2);
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
Dint_setone_sign(resultp1,resultp2);
|
||||
}
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
|
||||
if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
|
||||
(Dint_isone_lowp2(resultp2)))
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
else {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Dint_setzero(resultp1,resultp2);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Dbl_isnotzero_mantissa(srcp1,srcp2))
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
Dint_increment(resultp1,resultp2);
|
||||
}
|
||||
else {
|
||||
Dint_decrement(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
328
arch/parisc/math-emu/fcnvfxt.c
Обычный файл
328
arch/parisc/math-emu/fcnvfxt.c
Обычный файл
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Floating-point to Single Fixed-point /w truncated result
|
||||
* Single Floating-point to Double Fixed-point /w truncated result
|
||||
* Double Floating-point to Single Fixed-point /w truncated result
|
||||
* Double Floating-point to Double Fixed-point /w truncated result
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/*
|
||||
* Convert single floating-point to single fixed-point format
|
||||
* with truncated result
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_sgl_fcnvfxt(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
int *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, temp;
|
||||
register int src_exponent, result;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
|
||||
Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
|
||||
if (Sgl_iszero_sign(src)) result = 0x7fffffff;
|
||||
else result = 0x80000000;
|
||||
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
temp = src;
|
||||
Sgl_clear_signexponent_set_hidden(temp);
|
||||
Int_from_sgl_mantissa(temp,src_exponent);
|
||||
if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
|
||||
else result = Sgl_all(temp);
|
||||
*dstptr = result;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_fix(src,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dstptr = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Floating-point to Double Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_to_dbl_fcnvfxt(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_integer *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src_exponent, resultp1;
|
||||
register unsigned int src, temp, resultp2;
|
||||
|
||||
src = *srcptr;
|
||||
src_exponent = Sgl_exponent(src) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
|
||||
Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
|
||||
if (Sgl_iszero_sign(src)) {
|
||||
resultp1 = 0x7fffffff;
|
||||
resultp2 = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
resultp1 = 0x80000000;
|
||||
resultp2 = 0;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Dint_set_minint(resultp1,resultp2);
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
temp = src;
|
||||
Sgl_clear_signexponent_set_hidden(temp);
|
||||
Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
|
||||
if (Sgl_isone_sign(src)) {
|
||||
Dint_setone_sign(resultp1,resultp2);
|
||||
}
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_fix(src,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Dint_setzero(resultp1,resultp2);
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Single Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_sgl_fcnvfxt(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
int *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, tempp1, tempp2;
|
||||
register int src_exponent, result;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > SGL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
|
||||
if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
|
||||
else result = 0x80000000;
|
||||
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
tempp1 = srcp1;
|
||||
tempp2 = srcp2;
|
||||
Dbl_clear_signexponent_set_hidden(tempp1);
|
||||
Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
|
||||
if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
|
||||
result = -Dbl_allp1(tempp1);
|
||||
else result = Dbl_allp1(tempp1);
|
||||
*dstptr = result;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*dstptr = 0;
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point to Double Fixed-point
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_to_dbl_fcnvfxt(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_integer *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src_exponent, resultp1;
|
||||
register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (src_exponent > DBL_FX_MAX_EXP) {
|
||||
/* check for MININT */
|
||||
if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
|
||||
Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
|
||||
if (Dbl_iszero_sign(srcp1)) {
|
||||
resultp1 = 0x7fffffff;
|
||||
resultp2 = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
resultp1 = 0x80000000;
|
||||
resultp2 = 0;
|
||||
}
|
||||
if (Is_invalidtrap_enabled()) {
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
Set_invalidflag();
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
tempp1 = srcp1;
|
||||
tempp2 = srcp2;
|
||||
Dbl_clear_signexponent_set_hidden(tempp1);
|
||||
Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
|
||||
resultp1,resultp2);
|
||||
if (Dbl_isone_sign(srcp1)) {
|
||||
Dint_setone_sign(resultp1,resultp2);
|
||||
}
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Dint_setzero(resultp1,resultp2);
|
||||
Dint_copytoptr(resultp1,resultp2,dstptr);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
318
arch/parisc/math-emu/fcnvuf.c
Обычный файл
318
arch/parisc/math-emu/fcnvuf.c
Обычный файл
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Fixed point to Floating-point Converts
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/************************************************************************
|
||||
* Fixed point to Floating-point Converts *
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Convert Single Unsigned Fixed to Single Floating-point format
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_to_sgl_fcnvuf(
|
||||
unsigned int *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, result = 0;
|
||||
register int dst_exponent;
|
||||
|
||||
src = *srcptr;
|
||||
|
||||
/* Check for zero */
|
||||
if (src == 0) {
|
||||
Sgl_setzero(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(src,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
src <<= dst_exponent+1;
|
||||
Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
|
||||
Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Suint_isinexact_to_sgl(src)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Sgl_roundnearest_from_suint(src,result);
|
||||
break;
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
*dstptr = result;
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Unsigned Fixed to Double Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_to_dbl_fcnvuf(
|
||||
unsigned int *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int dst_exponent;
|
||||
register unsigned int src, resultp1 = 0, resultp2 = 0;
|
||||
|
||||
src = *srcptr;
|
||||
|
||||
/* Check for zero */
|
||||
if (src == 0) {
|
||||
Dbl_setzero(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(src,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
src <<= dst_exponent+1;
|
||||
Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
|
||||
Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
|
||||
Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Unsigned Fixed to Single Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_to_sgl_fcnvuf(
|
||||
dbl_unsigned *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
int dst_exponent;
|
||||
unsigned int srcp1, srcp2, result = 0;
|
||||
|
||||
Duint_copyfromptr(srcptr,srcp1,srcp2);
|
||||
|
||||
/* Check for zero */
|
||||
if (srcp1 == 0 && srcp2 == 0) {
|
||||
Sgl_setzero(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
if (srcp1 == 0) {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp2,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
srcp1 = srcp2 << dst_exponent+1;
|
||||
srcp2 = 0;
|
||||
/*
|
||||
* since msb set is in second word, need to
|
||||
* adjust bit position count
|
||||
*/
|
||||
dst_exponent += 32;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*
|
||||
*/
|
||||
Find_ms_one_bit(srcp1,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
if (dst_exponent >= 0) {
|
||||
Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
|
||||
srcp1);
|
||||
srcp2 <<= dst_exponent+1;
|
||||
}
|
||||
}
|
||||
Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
|
||||
Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Sgl_roundnearest_from_duint(srcp1,srcp2,result);
|
||||
break;
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
*dstptr = result;
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Unsigned Fixed to Double Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_to_dbl_fcnvuf(
|
||||
dbl_unsigned *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int dst_exponent;
|
||||
register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
|
||||
|
||||
Duint_copyfromptr(srcptr,srcp1,srcp2);
|
||||
|
||||
/* Check for zero */
|
||||
if (srcp1 == 0 && srcp2 ==0) {
|
||||
Dbl_setzero(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
if (srcp1 == 0) {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp2,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
srcp1 = srcp2 << dst_exponent+1;
|
||||
srcp2 = 0;
|
||||
/*
|
||||
* since msb set is in second word, need to
|
||||
* adjust bit position count
|
||||
*/
|
||||
dst_exponent += 32;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp1,dst_exponent);
|
||||
/* left justify source, with msb at bit position 0 */
|
||||
if (dst_exponent >= 0) {
|
||||
Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
|
||||
srcp1);
|
||||
srcp2 <<= dst_exponent+1;
|
||||
}
|
||||
}
|
||||
Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
|
||||
Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
|
||||
Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Duint_isinexact_to_dbl(srcp2)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDMINUS: /* never negative */
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Dbl_roundnearest_from_duint(srcp2,resultp1,
|
||||
resultp2);
|
||||
break;
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
386
arch/parisc/math-emu/fcnvxf.c
Обычный файл
386
arch/parisc/math-emu/fcnvxf.c
Обычный файл
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Fixed-point to Single Floating-point
|
||||
* Single Fixed-point to Double Floating-point
|
||||
* Double Fixed-point to Single Floating-point
|
||||
* Double Fixed-point to Double Floating-point
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
|
||||
* dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
|
||||
* sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/*
|
||||
* Convert single fixed-point to single floating-point format
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_to_sgl_fcnvxf(
|
||||
int *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src, dst_exponent;
|
||||
register unsigned int result = 0;
|
||||
|
||||
src = *srcptr;
|
||||
/*
|
||||
* set sign bit of result and get magnitude of source
|
||||
*/
|
||||
if (src < 0) {
|
||||
Sgl_setone_sign(result);
|
||||
Int_negate(src);
|
||||
}
|
||||
else {
|
||||
Sgl_setzero_sign(result);
|
||||
/* Check for zero */
|
||||
if (src == 0) {
|
||||
Sgl_setzero(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(src,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent >= 0) src <<= dst_exponent;
|
||||
else src = 1 << 30;
|
||||
Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
|
||||
Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Int_isinexact_to_sgl(src)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result))
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result))
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Sgl_roundnearest_from_int(src,result);
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
*dstptr = result;
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Single Fixed-point to Double Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_to_dbl_fcnvxf(
|
||||
int *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int src, dst_exponent;
|
||||
register unsigned int resultp1 = 0, resultp2 = 0;
|
||||
|
||||
src = *srcptr;
|
||||
/*
|
||||
* set sign bit of result and get magnitude of source
|
||||
*/
|
||||
if (src < 0) {
|
||||
Dbl_setone_sign(resultp1);
|
||||
Int_negate(src);
|
||||
}
|
||||
else {
|
||||
Dbl_setzero_sign(resultp1);
|
||||
/* Check for zero */
|
||||
if (src == 0) {
|
||||
Dbl_setzero(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(src,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent >= 0) src <<= dst_exponent;
|
||||
else src = 1 << 30;
|
||||
Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
|
||||
Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
|
||||
Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Fixed-point to Single Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_to_sgl_fcnvxf(
|
||||
dbl_integer *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
int dst_exponent, srcp1;
|
||||
unsigned int result = 0, srcp2;
|
||||
|
||||
Dint_copyfromptr(srcptr,srcp1,srcp2);
|
||||
/*
|
||||
* set sign bit of result and get magnitude of source
|
||||
*/
|
||||
if (srcp1 < 0) {
|
||||
Sgl_setone_sign(result);
|
||||
Dint_negate(srcp1,srcp2);
|
||||
}
|
||||
else {
|
||||
Sgl_setzero_sign(result);
|
||||
/* Check for zero */
|
||||
if (srcp1 == 0 && srcp2 == 0) {
|
||||
Sgl_setzero(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
if (srcp1 == 0) {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp2,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent >= 0) {
|
||||
srcp1 = srcp2 << dst_exponent;
|
||||
srcp2 = 0;
|
||||
}
|
||||
else {
|
||||
srcp1 = srcp2 >> 1;
|
||||
srcp2 <<= 31;
|
||||
}
|
||||
/*
|
||||
* since msb set is in second word, need to
|
||||
* adjust bit position count
|
||||
*/
|
||||
dst_exponent += 32;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*
|
||||
*/
|
||||
Find_ms_one_bit(srcp1,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent > 0) {
|
||||
Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
|
||||
srcp1);
|
||||
srcp2 <<= dst_exponent;
|
||||
}
|
||||
/*
|
||||
* If dst_exponent = 0, we don't need to shift anything.
|
||||
* If dst_exponent = -1, src = - 2**63 so we won't need to
|
||||
* shift srcp2.
|
||||
*/
|
||||
else srcp1 >>= -(dst_exponent);
|
||||
}
|
||||
Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
|
||||
Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result))
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result))
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Sgl_roundnearest_from_dint(srcp1,srcp2,result);
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
*dstptr = result;
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Fixed-point to Double Floating-point
|
||||
*/
|
||||
|
||||
int
|
||||
dbl_to_dbl_fcnvxf(
|
||||
dbl_integer *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register int srcp1, dst_exponent;
|
||||
register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
|
||||
|
||||
Dint_copyfromptr(srcptr,srcp1,srcp2);
|
||||
/*
|
||||
* set sign bit of result and get magnitude of source
|
||||
*/
|
||||
if (srcp1 < 0) {
|
||||
Dbl_setone_sign(resultp1);
|
||||
Dint_negate(srcp1,srcp2);
|
||||
}
|
||||
else {
|
||||
Dbl_setzero_sign(resultp1);
|
||||
/* Check for zero */
|
||||
if (srcp1 == 0 && srcp2 ==0) {
|
||||
Dbl_setzero(resultp1,resultp2);
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Generate exponent and normalized mantissa
|
||||
*/
|
||||
dst_exponent = 16; /* initialize for normalization */
|
||||
if (srcp1 == 0) {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp2,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent >= 0) {
|
||||
srcp1 = srcp2 << dst_exponent;
|
||||
srcp2 = 0;
|
||||
}
|
||||
else {
|
||||
srcp1 = srcp2 >> 1;
|
||||
srcp2 <<= 31;
|
||||
}
|
||||
/*
|
||||
* since msb set is in second word, need to
|
||||
* adjust bit position count
|
||||
*/
|
||||
dst_exponent += 32;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Check word for most significant bit set. Returns
|
||||
* a value in dst_exponent indicating the bit position,
|
||||
* between -1 and 30.
|
||||
*/
|
||||
Find_ms_one_bit(srcp1,dst_exponent);
|
||||
/* left justify source, with msb at bit position 1 */
|
||||
if (dst_exponent > 0) {
|
||||
Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
|
||||
srcp1);
|
||||
srcp2 <<= dst_exponent;
|
||||
}
|
||||
/*
|
||||
* If dst_exponent = 0, we don't need to shift anything.
|
||||
* If dst_exponent = -1, src = - 2**63 so we won't need to
|
||||
* shift srcp2.
|
||||
*/
|
||||
else srcp1 >>= -(dst_exponent);
|
||||
}
|
||||
Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
|
||||
Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
|
||||
Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
|
||||
|
||||
/* check for inexact */
|
||||
if (Dint_isinexact_to_dbl(srcp2)) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(resultp1)) {
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(resultp1)) {
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
Dbl_roundnearest_from_dint(srcp2,resultp1,
|
||||
resultp2);
|
||||
}
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
582
arch/parisc/math-emu/float.h
Обычный файл
582
arch/parisc/math-emu/float.h
Обычный файл
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/float.h $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* <<please update with a synopis of the functionality provided by this file>>
|
||||
*
|
||||
* BE header: no
|
||||
*
|
||||
* Shipped: yes
|
||||
* /usr/conf/pa/spmath/float.h
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
#include "fpbits.h"
|
||||
#include "hppa.h"
|
||||
/*
|
||||
* Want to pick up the FPU capability flags, not the PDC structures.
|
||||
* 'LOCORE' isn't really true in this case, but we don't want the C structures
|
||||
* so it suits our purposes
|
||||
*/
|
||||
#define LOCORE
|
||||
#include "fpu.h"
|
||||
|
||||
/*
|
||||
* Declare the basic structures for the 3 different
|
||||
* floating-point precisions.
|
||||
*
|
||||
* Single number
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| exp | mantissa |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#define Sall(object) (object)
|
||||
#define Ssign(object) Bitfield_extract( 0, 1,object)
|
||||
#define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object)
|
||||
#define Sexponent(object) Bitfield_extract( 1, 8,object)
|
||||
#define Smantissa(object) Bitfield_mask( 9, 23,object)
|
||||
#define Ssignaling(object) Bitfield_extract( 9, 1,object)
|
||||
#define Ssignalingnan(object) Bitfield_extract( 1, 9,object)
|
||||
#define Shigh2mantissa(object) Bitfield_extract( 9, 2,object)
|
||||
#define Sexponentmantissa(object) Bitfield_mask( 1, 31,object)
|
||||
#define Ssignexponent(object) Bitfield_extract( 0, 9,object)
|
||||
#define Shidden(object) Bitfield_extract( 8, 1,object)
|
||||
#define Shiddenoverflow(object) Bitfield_extract( 7, 1,object)
|
||||
#define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object)
|
||||
#define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object)
|
||||
#define Slow(object) Bitfield_mask( 31, 1,object)
|
||||
#define Slow4(object) Bitfield_mask( 28, 4,object)
|
||||
#define Slow31(object) Bitfield_mask( 1, 31,object)
|
||||
#define Shigh31(object) Bitfield_extract( 0, 31,object)
|
||||
#define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object)
|
||||
#define Shigh4(object) Bitfield_extract( 0, 4,object)
|
||||
#define Sbit24(object) Bitfield_extract( 24, 1,object)
|
||||
#define Sbit28(object) Bitfield_extract( 28, 1,object)
|
||||
#define Sbit29(object) Bitfield_extract( 29, 1,object)
|
||||
#define Sbit30(object) Bitfield_extract( 30, 1,object)
|
||||
#define Sbit31(object) Bitfield_mask( 31, 1,object)
|
||||
|
||||
#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object)
|
||||
#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object)
|
||||
#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object)
|
||||
#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object)
|
||||
#define Deposit_sexponentmantissa(object,value) \
|
||||
Bitfield_deposit(value,1,31,object)
|
||||
#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object)
|
||||
#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object)
|
||||
#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object)
|
||||
|
||||
#define Is_ssign(object) Bitfield_mask( 0, 1,object)
|
||||
#define Is_ssignaling(object) Bitfield_mask( 9, 1,object)
|
||||
#define Is_shidden(object) Bitfield_mask( 8, 1,object)
|
||||
#define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object)
|
||||
#define Is_slow(object) Bitfield_mask( 31, 1,object)
|
||||
#define Is_sbit24(object) Bitfield_mask( 24, 1,object)
|
||||
#define Is_sbit28(object) Bitfield_mask( 28, 1,object)
|
||||
#define Is_sbit29(object) Bitfield_mask( 29, 1,object)
|
||||
#define Is_sbit30(object) Bitfield_mask( 30, 1,object)
|
||||
#define Is_sbit31(object) Bitfield_mask( 31, 1,object)
|
||||
|
||||
/*
|
||||
* Double number.
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| exponent | mantissa part 1 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | mantissa part 2 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#define Dallp1(object) (object)
|
||||
#define Dsign(object) Bitfield_extract( 0, 1,object)
|
||||
#define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object)
|
||||
#define Dexponent(object) Bitfield_extract( 1, 11,object)
|
||||
#define Dmantissap1(object) Bitfield_mask( 12, 20,object)
|
||||
#define Dsignaling(object) Bitfield_extract( 12, 1,object)
|
||||
#define Dsignalingnan(object) Bitfield_extract( 1, 12,object)
|
||||
#define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object)
|
||||
#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object)
|
||||
#define Dsignexponent(object) Bitfield_extract( 0, 12,object)
|
||||
#define Dhidden(object) Bitfield_extract( 11, 1,object)
|
||||
#define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object)
|
||||
#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object)
|
||||
#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object)
|
||||
#define Dlowp1(object) Bitfield_mask( 31, 1,object)
|
||||
#define Dlow31p1(object) Bitfield_mask( 1, 31,object)
|
||||
#define Dhighp1(object) Bitfield_extract( 0, 1,object)
|
||||
#define Dhigh4p1(object) Bitfield_extract( 0, 4,object)
|
||||
#define Dhigh31p1(object) Bitfield_extract( 0, 31,object)
|
||||
#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object)
|
||||
#define Dbit3p1(object) Bitfield_extract( 3, 1,object)
|
||||
|
||||
#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object)
|
||||
#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object)
|
||||
#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object)
|
||||
#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object)
|
||||
#define Deposit_dexponentmantissap1(object,value) \
|
||||
Bitfield_deposit(value,1,31,object)
|
||||
#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object)
|
||||
#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object)
|
||||
#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object)
|
||||
|
||||
#define Is_dsign(object) Bitfield_mask( 0, 1,object)
|
||||
#define Is_dsignaling(object) Bitfield_mask( 12, 1,object)
|
||||
#define Is_dhidden(object) Bitfield_mask( 11, 1,object)
|
||||
#define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object)
|
||||
#define Is_dlowp1(object) Bitfield_mask( 31, 1,object)
|
||||
#define Is_dhighp1(object) Bitfield_mask( 0, 1,object)
|
||||
#define Is_dbit3p1(object) Bitfield_mask( 3, 1,object)
|
||||
|
||||
#define Dallp2(object) (object)
|
||||
#define Dmantissap2(object) (object)
|
||||
#define Dlowp2(object) Bitfield_mask( 31, 1,object)
|
||||
#define Dlow4p2(object) Bitfield_mask( 28, 4,object)
|
||||
#define Dlow31p2(object) Bitfield_mask( 1, 31,object)
|
||||
#define Dhighp2(object) Bitfield_extract( 0, 1,object)
|
||||
#define Dhigh31p2(object) Bitfield_extract( 0, 31,object)
|
||||
#define Dbit2p2(object) Bitfield_extract( 2, 1,object)
|
||||
#define Dbit3p2(object) Bitfield_extract( 3, 1,object)
|
||||
#define Dbit21p2(object) Bitfield_extract( 21, 1,object)
|
||||
#define Dbit28p2(object) Bitfield_extract( 28, 1,object)
|
||||
#define Dbit29p2(object) Bitfield_extract( 29, 1,object)
|
||||
#define Dbit30p2(object) Bitfield_extract( 30, 1,object)
|
||||
#define Dbit31p2(object) Bitfield_mask( 31, 1,object)
|
||||
|
||||
#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object)
|
||||
|
||||
#define Is_dlowp2(object) Bitfield_mask( 31, 1,object)
|
||||
#define Is_dhighp2(object) Bitfield_mask( 0, 1,object)
|
||||
#define Is_dbit2p2(object) Bitfield_mask( 2, 1,object)
|
||||
#define Is_dbit3p2(object) Bitfield_mask( 3, 1,object)
|
||||
#define Is_dbit21p2(object) Bitfield_mask( 21, 1,object)
|
||||
#define Is_dbit28p2(object) Bitfield_mask( 28, 1,object)
|
||||
#define Is_dbit29p2(object) Bitfield_mask( 29, 1,object)
|
||||
#define Is_dbit30p2(object) Bitfield_mask( 30, 1,object)
|
||||
#define Is_dbit31p2(object) Bitfield_mask( 31, 1,object)
|
||||
|
||||
/*
|
||||
* Quad number.
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| exponent | mantissa part 1 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | mantissa part 2 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | mantissa part 3 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | mantissa part 4 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct { unsigned qallp1; } u_qallp1;
|
||||
/* Not needed for now...
|
||||
Bitfield_extract( 0, 1,u_qsign,qsign)
|
||||
Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign)
|
||||
Bitfield_extract( 1, 15,u_qexponent,qexponent)
|
||||
Bitfield_extract(16, 16,u_qmantissap1,qmantissap1)
|
||||
Bitfield_extract(16, 1,u_qsignaling,qsignaling)
|
||||
Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan)
|
||||
Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa)
|
||||
Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1)
|
||||
Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent)
|
||||
Bitfield_extract(15, 1,u_qhidden,qhidden)
|
||||
Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow)
|
||||
Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa)
|
||||
Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa)
|
||||
Bitfield_extract(31, 1,u_qlowp1,qlowp1)
|
||||
Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1)
|
||||
Bitfield_extract( 0, 1,u_qhighp1,qhighp1)
|
||||
Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1)
|
||||
Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1)
|
||||
*/
|
||||
} quad_u1;
|
||||
union
|
||||
{
|
||||
struct { unsigned qallp2; } u_qallp2;
|
||||
/* Not needed for now...
|
||||
Bitfield_extract(31, 1,u_qlowp2,qlowp2)
|
||||
Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2)
|
||||
Bitfield_extract( 0, 1,u_qhighp2,qhighp2)
|
||||
Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2)
|
||||
*/
|
||||
} quad_u2;
|
||||
union
|
||||
{
|
||||
struct { unsigned qallp3; } u_qallp3;
|
||||
/* Not needed for now...
|
||||
Bitfield_extract(31, 1,u_qlowp3,qlowp3)
|
||||
Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3)
|
||||
Bitfield_extract( 0, 1,u_qhighp3,qhighp3)
|
||||
Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3)
|
||||
*/
|
||||
} quad_u3;
|
||||
union
|
||||
{
|
||||
struct { unsigned qallp4; } u_qallp4;
|
||||
/* Not need for now...
|
||||
Bitfield_extract(31, 1,u_qlowp4,qlowp4)
|
||||
Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4)
|
||||
Bitfield_extract( 0, 1,u_qhighp4,qhighp4)
|
||||
Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4)
|
||||
*/
|
||||
} quad_u4;
|
||||
} quad_floating_point;
|
||||
|
||||
/* Extension - An additional structure to hold the guard, round and
|
||||
* sticky bits during computations.
|
||||
*/
|
||||
#define Extall(object) (object)
|
||||
#define Extsign(object) Bitfield_extract( 0, 1,object)
|
||||
#define Exthigh31(object) Bitfield_extract( 0, 31,object)
|
||||
#define Extlow31(object) Bitfield_extract( 1, 31,object)
|
||||
#define Extlow(object) Bitfield_extract( 31, 1,object)
|
||||
|
||||
/*
|
||||
* Single extended - The upper word is just like single precision,
|
||||
* but one additional word of mantissa is needed.
|
||||
*/
|
||||
#define Sextallp1(object) (object)
|
||||
#define Sextallp2(object) (object)
|
||||
#define Sextlowp1(object) Bitfield_extract( 31, 1,object)
|
||||
#define Sexthighp2(object) Bitfield_extract( 0, 1,object)
|
||||
#define Sextlow31p2(object) Bitfield_extract( 1, 31,object)
|
||||
#define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object)
|
||||
#define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object)
|
||||
|
||||
/*
|
||||
* Double extended - The upper two words are just like double precision,
|
||||
* but two additional words of mantissa are needed.
|
||||
*/
|
||||
#define Dextallp1(object) (object)
|
||||
#define Dextallp2(object) (object)
|
||||
#define Dextallp3(object) (object)
|
||||
#define Dextallp4(object) (object)
|
||||
#define Dextlowp2(object) Bitfield_extract( 31, 1,object)
|
||||
#define Dexthighp3(object) Bitfield_extract( 0, 1,object)
|
||||
#define Dextlow31p3(object) Bitfield_extract( 1, 31,object)
|
||||
#define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object)
|
||||
#define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object)
|
||||
#define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object)
|
||||
|
||||
/*
|
||||
* Declare the basic structures for the 3 different
|
||||
* fixed-point precisions.
|
||||
*
|
||||
* Single number
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| integer |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
typedef int sgl_integer;
|
||||
|
||||
/*
|
||||
* Double number.
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| high integer |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | low integer |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
struct dint {
|
||||
int wd0;
|
||||
unsigned int wd1;
|
||||
};
|
||||
|
||||
struct dblwd {
|
||||
unsigned int wd0;
|
||||
unsigned int wd1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Quad number.
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |s| integer part1 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | integer part 2 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | integer part 3 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | integer part 4 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
|
||||
struct quadwd {
|
||||
int wd0;
|
||||
unsigned int wd1;
|
||||
unsigned int wd2;
|
||||
unsigned int wd3;
|
||||
};
|
||||
|
||||
typedef struct quadwd quad_integer;
|
||||
|
||||
|
||||
/* useful typedefs */
|
||||
typedef unsigned int sgl_floating_point;
|
||||
typedef struct dblwd dbl_floating_point;
|
||||
typedef struct dint dbl_integer;
|
||||
typedef struct dblwd dbl_unsigned;
|
||||
|
||||
/*
|
||||
* Define the different precisions' parameters.
|
||||
*/
|
||||
#define SGL_BITLENGTH 32
|
||||
#define SGL_EMAX 127
|
||||
#define SGL_EMIN (-126)
|
||||
#define SGL_BIAS 127
|
||||
#define SGL_WRAP 192
|
||||
#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1)
|
||||
#define SGL_THRESHOLD 32
|
||||
#define SGL_EXP_LENGTH 8
|
||||
#define SGL_P 24
|
||||
|
||||
#define DBL_BITLENGTH 64
|
||||
#define DBL_EMAX 1023
|
||||
#define DBL_EMIN (-1022)
|
||||
#define DBL_BIAS 1023
|
||||
#define DBL_WRAP 1536
|
||||
#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1)
|
||||
#define DBL_THRESHOLD 64
|
||||
#define DBL_EXP_LENGTH 11
|
||||
#define DBL_P 53
|
||||
|
||||
#define QUAD_BITLENGTH 128
|
||||
#define QUAD_EMAX 16383
|
||||
#define QUAD_EMIN (-16382)
|
||||
#define QUAD_BIAS 16383
|
||||
#define QUAD_WRAP 24576
|
||||
#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1)
|
||||
#define QUAD_P 113
|
||||
|
||||
/* Boolean Values etc. */
|
||||
#define FALSE 0
|
||||
#define TRUE (!FALSE)
|
||||
#define NOT !
|
||||
#define XOR ^
|
||||
|
||||
/* other constants */
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
#define NIL 0
|
||||
#define SGL 0
|
||||
#define DBL 1
|
||||
#define BADFMT 2
|
||||
#define QUAD 3
|
||||
|
||||
|
||||
/* Types */
|
||||
typedef int boolean;
|
||||
typedef int FORMAT;
|
||||
typedef int VOID;
|
||||
|
||||
|
||||
/* Declare status register equivalent to FPUs architecture.
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I|
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#define Cbit(object) Bitfield_extract( 5, 1,object)
|
||||
#define Tbit(object) Bitfield_extract( 25, 1,object)
|
||||
#define Roundingmode(object) Bitfield_extract( 21, 2,object)
|
||||
#define Invalidtrap(object) Bitfield_extract( 27, 1,object)
|
||||
#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object)
|
||||
#define Overflowtrap(object) Bitfield_extract( 29, 1,object)
|
||||
#define Underflowtrap(object) Bitfield_extract( 30, 1,object)
|
||||
#define Inexacttrap(object) Bitfield_extract( 31, 1,object)
|
||||
#define Invalidflag(object) Bitfield_extract( 0, 1,object)
|
||||
#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object)
|
||||
#define Overflowflag(object) Bitfield_extract( 2, 1,object)
|
||||
#define Underflowflag(object) Bitfield_extract( 3, 1,object)
|
||||
#define Inexactflag(object) Bitfield_extract( 4, 1,object)
|
||||
#define Allflags(object) Bitfield_extract( 0, 5,object)
|
||||
|
||||
/* Definitions relevant to the status register */
|
||||
|
||||
/* Rounding Modes */
|
||||
#define ROUNDNEAREST 0
|
||||
#define ROUNDZERO 1
|
||||
#define ROUNDPLUS 2
|
||||
#define ROUNDMINUS 3
|
||||
|
||||
/* Exceptions */
|
||||
#define NOEXCEPTION 0x0
|
||||
#define INVALIDEXCEPTION 0x20
|
||||
#define DIVISIONBYZEROEXCEPTION 0x10
|
||||
#define OVERFLOWEXCEPTION 0x08
|
||||
#define UNDERFLOWEXCEPTION 0x04
|
||||
#define INEXACTEXCEPTION 0x02
|
||||
#define UNIMPLEMENTEDEXCEPTION 0x01
|
||||
|
||||
/* New exceptions for the 2E Opcode */
|
||||
#define OPC_2E_INVALIDEXCEPTION 0x30
|
||||
#define OPC_2E_OVERFLOWEXCEPTION 0x18
|
||||
#define OPC_2E_UNDERFLOWEXCEPTION 0x0c
|
||||
#define OPC_2E_INEXACTEXCEPTION 0x12
|
||||
|
||||
/* Declare exception registers equivalent to FPUs architecture
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* |excepttype | r1 | r2/ext | operation |parm |n| t/cond |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#define Allexception(object) (object)
|
||||
#define Exceptiontype(object) Bitfield_extract( 0, 6,object)
|
||||
#define Instructionfield(object) Bitfield_mask( 6,26,object)
|
||||
#define Parmfield(object) Bitfield_extract( 23, 3,object)
|
||||
#define Rabit(object) Bitfield_extract( 24, 1,object)
|
||||
#define Ibit(object) Bitfield_extract( 25, 1,object)
|
||||
|
||||
#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object)
|
||||
#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object)
|
||||
#define Set_exceptiontype_and_instr_field(exception,instruction,object) \
|
||||
object = exception << 26 | instruction
|
||||
|
||||
/* Declare the condition field
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | |G|L|E|U|X|
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*/
|
||||
#define Allexception(object) (object)
|
||||
#define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
|
||||
#define Lessthanbit(object) Bitfield_extract( 28, 1,object)
|
||||
#define Equalbit(object) Bitfield_extract( 29, 1,object)
|
||||
#define Unorderedbit(object) Bitfield_extract( 30, 1,object)
|
||||
#define Exceptionbit(object) Bitfield_extract( 31, 1,object)
|
||||
|
||||
/* An alias name for the status register */
|
||||
#define Fpustatus_register (*status)
|
||||
|
||||
/**************************************************
|
||||
* Status register referencing and manipulation. *
|
||||
**************************************************/
|
||||
|
||||
/* Rounding mode */
|
||||
#define Rounding_mode() Roundingmode(Fpustatus_register)
|
||||
#define Is_rounding_mode(rmode) \
|
||||
(Roundingmode(Fpustatus_register) == rmode)
|
||||
#define Set_rounding_mode(value) \
|
||||
Bitfield_deposit(value,21,2,Fpustatus_register)
|
||||
|
||||
/* Boolean testing of the trap enable bits */
|
||||
#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register)
|
||||
#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register)
|
||||
#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register)
|
||||
#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register)
|
||||
#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register)
|
||||
|
||||
/* Set the indicated flags in the status register */
|
||||
#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register)
|
||||
#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register)
|
||||
#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register)
|
||||
#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register)
|
||||
#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register)
|
||||
|
||||
#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register)
|
||||
|
||||
/* Manipulate the trap and condition code bits (tbit and cbit) */
|
||||
#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register)
|
||||
#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register)
|
||||
#define Is_tbit_set() Tbit(Fpustatus_register)
|
||||
#define Is_cbit_set() Cbit(Fpustatus_register)
|
||||
|
||||
#define Set_status_cbit(value) \
|
||||
Bitfield_deposit(value,5,1,Fpustatus_register)
|
||||
|
||||
/*******************************
|
||||
* Condition field referencing *
|
||||
*******************************/
|
||||
#define Unordered(cond) Unorderedbit(cond)
|
||||
#define Equal(cond) Equalbit(cond)
|
||||
#define Lessthan(cond) Lessthanbit(cond)
|
||||
#define Greaterthan(cond) Greaterthanbit(cond)
|
||||
#define Exception(cond) Exceptionbit(cond)
|
||||
|
||||
|
||||
/* Defines for the extension */
|
||||
#define Ext_isone_sign(extent) (Extsign(extent))
|
||||
#define Ext_isnotzero(extent) \
|
||||
(Extall(extent))
|
||||
#define Ext_isnotzero_lower(extent) \
|
||||
(Extlow31(extent))
|
||||
#define Ext_leftshiftby1(extent) \
|
||||
Extall(extent) <<= 1
|
||||
#define Ext_negate(extent) \
|
||||
(int )Extall(extent) = 0 - (int )Extall(extent)
|
||||
#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent)
|
||||
#define Ext_setzero(extent) Extall(extent) = 0
|
||||
|
||||
typedef int operation;
|
||||
|
||||
/* error messages */
|
||||
|
||||
#define NONE 0
|
||||
#define UNDEFFPINST 1
|
||||
|
||||
/* Function definitions: opcode, opclass */
|
||||
#define FTEST (1<<2) | 0
|
||||
#define FCPY (2<<2) | 0
|
||||
#define FABS (3<<2) | 0
|
||||
#define FSQRT (4<<2) | 0
|
||||
#define FRND (5<<2) | 0
|
||||
|
||||
#define FCNVFF (0<<2) | 1
|
||||
#define FCNVXF (1<<2) | 1
|
||||
#define FCNVFX (2<<2) | 1
|
||||
#define FCNVFXT (3<<2) | 1
|
||||
|
||||
#define FCMP (0<<2) | 2
|
||||
|
||||
#define FADD (0<<2) | 3
|
||||
#define FSUB (1<<2) | 3
|
||||
#define FMPY (2<<2) | 3
|
||||
#define FDIV (3<<2) | 3
|
||||
#define FREM (4<<2) | 3
|
||||
|
2655
arch/parisc/math-emu/fmpyfadd.c
Обычный файл
2655
arch/parisc/math-emu/fmpyfadd.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
65
arch/parisc/math-emu/fpbits.h
Обычный файл
65
arch/parisc/math-emu/fpbits.h
Обычный файл
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These macros are designed to be portable to all machines that have
|
||||
* a wordsize greater than or equal to 32 bits that support the portable
|
||||
* C compiler and the standard C preprocessor. Wordsize (default 32)
|
||||
* and bitfield assignment (default left-to-right, unlike VAX, PDP-11)
|
||||
* should be predefined using the constants HOSTWDSZ and BITFRL and
|
||||
* the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20).
|
||||
* Note that the macro arguments assume that the integer being referenced
|
||||
* is a 32-bit integer (right-justified on the 20) and that bit 0 is the
|
||||
* most significant bit.
|
||||
*/
|
||||
|
||||
#ifndef HOSTWDSZ
|
||||
#define HOSTWDSZ 32
|
||||
#endif
|
||||
|
||||
|
||||
/*########################### Macros ######################################*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* NewDeclareBitField_Reference - Declare a structure similar to the simulator
|
||||
* function "DeclBitfR" except its use is restricted to occur within a larger
|
||||
* enclosing structure or union definition. This declaration is an unnamed
|
||||
* structure with the argument, name, as the member name and the argument,
|
||||
* uname, as the element name.
|
||||
*----------------------------------------------------------------------- */
|
||||
#define Bitfield_extract(start, length, object) \
|
||||
((object) >> (HOSTWDSZ - (start) - (length)) & \
|
||||
((unsigned)-1 >> (HOSTWDSZ - (length))))
|
||||
|
||||
#define Bitfield_signed_extract(start, length, object) \
|
||||
((int)((object) << start) >> (HOSTWDSZ - (length)))
|
||||
|
||||
#define Bitfield_mask(start, len, object) \
|
||||
((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len)))
|
||||
|
||||
#define Bitfield_deposit(value,start,len,object) object = \
|
||||
((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \
|
||||
(((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len))
|
76
arch/parisc/math-emu/fpu.h
Обычный файл
76
arch/parisc/math-emu/fpu.h
Обычный файл
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/fp/fpu.h $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* <<please update with a synopis of the functionality provided by this file>>
|
||||
*
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */
|
||||
#define _MACHINE_FPU_INCLUDED
|
||||
|
||||
#if 0
|
||||
#ifndef _SYS_STDSYMS_INCLUDED
|
||||
# include <sys/stdsyms.h>
|
||||
#endif /* _SYS_STDSYMS_INCLUDED */
|
||||
#include <machine/pdc/pdc_rqsts.h>
|
||||
#endif
|
||||
|
||||
#define PA83_FPU_FLAG 0x00000001
|
||||
#define PA89_FPU_FLAG 0x00000002
|
||||
#define PA2_0_FPU_FLAG 0x00000010
|
||||
|
||||
#define TIMEX_EXTEN_FLAG 0x00000004
|
||||
|
||||
#define ROLEX_EXTEN_FLAG 0x00000008
|
||||
#define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */
|
||||
#define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */
|
||||
|
||||
|
||||
#define EM_FPU_TYPE_OFFSET 272
|
||||
|
||||
/* version of EMULATION software for COPR,0,0 instruction */
|
||||
#define EMULATION_VERSION 4
|
||||
|
||||
/*
|
||||
* The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T)
|
||||
* is thorough the potential type field from the PDC_MODEL call. The
|
||||
* following flags are used at assist this differeniation.
|
||||
*/
|
||||
|
||||
#define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO
|
||||
#define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \
|
||||
PDC_MODEL_CPU_KEY_RECIP_SQRT)
|
||||
|
||||
|
||||
#endif /* ! _MACHINE_FPU_INCLUDED */
|
1442
arch/parisc/math-emu/fpudispatch.c
Обычный файл
1442
arch/parisc/math-emu/fpudispatch.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
252
arch/parisc/math-emu/frnd.c
Обычный файл
252
arch/parisc/math-emu/frnd.c
Обычный файл
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* Purpose:
|
||||
* Single Floating-point Round to Integer
|
||||
* Double Floating-point Round to Integer
|
||||
* Quad Floating-point Round to Integer (returns unimplemented)
|
||||
*
|
||||
* External Interfaces:
|
||||
* dbl_frnd(srcptr,nullptr,dstptr,status)
|
||||
* sgl_frnd(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
#include "dbl_float.h"
|
||||
#include "cnv_float.h"
|
||||
|
||||
/*
|
||||
* Single Floating-point Round to Integer
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
sgl_frnd(sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, result;
|
||||
register int src_exponent;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
src = *srcptr;
|
||||
/*
|
||||
* check source operand for NaN or infinity
|
||||
*/
|
||||
if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* is signaling NaN?
|
||||
*/
|
||||
if (Sgl_isone_signaling(src)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(src);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN or infinity
|
||||
*/
|
||||
*dstptr = src;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Need to round?
|
||||
*/
|
||||
if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
|
||||
*dstptr = src;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
Sgl_clear_exponent_set_hidden(src);
|
||||
result = src;
|
||||
Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
|
||||
/* check for inexact */
|
||||
if (Sgl_isinexact_to_fix(src,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src)) Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src)) Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Sgl_isone_roundbit(src,src_exponent))
|
||||
if (Sgl_isone_stickybit(src,src_exponent)
|
||||
|| (Sgl_isone_lowmantissa(result)))
|
||||
Sgl_increment(result);
|
||||
}
|
||||
}
|
||||
Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
|
||||
if (Sgl_isone_hiddenoverflow(result))
|
||||
Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
|
||||
else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
|
||||
}
|
||||
else {
|
||||
result = src; /* set sign */
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero_exponentmantissa(src)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(src))
|
||||
Sgl_set_exponent(result,SGL_BIAS);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(src))
|
||||
Sgl_set_exponent(result,SGL_BIAS);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Sgl_isnotzero_mantissa(src))
|
||||
Sgl_set_exponent(result,SGL_BIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
*dstptr = result;
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Double Floating-point Round to Integer
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
dbl_frnd(
|
||||
dbl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
dbl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int srcp1, srcp2, resultp1, resultp2;
|
||||
register int src_exponent;
|
||||
register boolean inexact = FALSE;
|
||||
|
||||
Dbl_copyfromptr(srcptr,srcp1,srcp2);
|
||||
/*
|
||||
* check source operand for NaN or infinity
|
||||
*/
|
||||
if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* is signaling NaN?
|
||||
*/
|
||||
if (Dbl_isone_signaling(srcp1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Dbl_set_quiet(srcp1);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN or infinity
|
||||
*/
|
||||
Dbl_copytoptr(srcp1,srcp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Need to round?
|
||||
*/
|
||||
if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
|
||||
Dbl_copytoptr(srcp1,srcp2,dstptr);
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent >= 0) {
|
||||
Dbl_clear_exponent_set_hidden(srcp1);
|
||||
resultp1 = srcp1;
|
||||
resultp2 = srcp2;
|
||||
Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
|
||||
/* check for inexact */
|
||||
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1))
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1))
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
|
||||
if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
|
||||
|| (Dbl_isone_lowmantissap2(resultp2)))
|
||||
Dbl_increment(resultp1,resultp2);
|
||||
}
|
||||
}
|
||||
Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
|
||||
if (Dbl_isone_hiddenoverflow(resultp1))
|
||||
Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
|
||||
else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
|
||||
}
|
||||
else {
|
||||
resultp1 = srcp1; /* set sign */
|
||||
Dbl_setzero_exponentmantissa(resultp1,resultp2);
|
||||
/* check for inexact */
|
||||
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
|
||||
inexact = TRUE;
|
||||
/* round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Dbl_iszero_sign(srcp1))
|
||||
Dbl_set_exponent(resultp1,DBL_BIAS);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Dbl_isone_sign(srcp1))
|
||||
Dbl_set_exponent(resultp1,DBL_BIAS);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (src_exponent == -1)
|
||||
if (Dbl_isnotzero_mantissa(srcp1,srcp2))
|
||||
Dbl_set_exponent(resultp1,DBL_BIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
Dbl_copytoptr(resultp1,resultp2,dstptr);
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
42
arch/parisc/math-emu/hppa.h
Обычный файл
42
arch/parisc/math-emu/hppa.h
Обычный файл
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
|
||||
/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */
|
||||
#define Shiftdouble(left,right,amount,dest) \
|
||||
/* int left, right, amount, dest; */ \
|
||||
dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount))
|
||||
|
||||
/* amount must be less than 32 */
|
||||
#define Variableshiftdouble(left,right,amount,dest) \
|
||||
/* unsigned int left, right; int amount, dest; */ \
|
||||
if (amount == 0) dest = right; \
|
||||
else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \
|
||||
((unsigned) right >> (amount))
|
||||
|
||||
/* amount must be between 0 and 32 (non-inclusive) */
|
||||
#define Variable_shift_double(left,right,amount,dest) \
|
||||
/* unsigned int left, right; int amount, dest; */ \
|
||||
dest = (left << (32-(amount))) | ((unsigned) right >> (amount))
|
27
arch/parisc/math-emu/math-emu.h
Обычный файл
27
arch/parisc/math-emu/math-emu.h
Обычный файл
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PARISC_MATH_EMU_H
|
||||
#define _PARISC_MATH_EMU_H
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
extern int handle_fpe(struct pt_regs *regs);
|
||||
|
||||
#endif
|
518
arch/parisc/math-emu/sfadd.c
Обычный файл
518
arch/parisc/math-emu/sfadd.c
Обычный файл
@@ -0,0 +1,518 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfadd.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single_add: add two single precision values.
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fadd(leftptr, rightptr, dstptr, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single_add: add two single precision values.
|
||||
*/
|
||||
int
|
||||
sgl_fadd(
|
||||
sgl_floating_point *leftptr,
|
||||
sgl_floating_point *rightptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int left, right, result, extent;
|
||||
register unsigned int signless_upper_left, signless_upper_right, save;
|
||||
|
||||
|
||||
register int result_exponent, right_exponent, diff_exponent;
|
||||
register int sign_save, jumpsize;
|
||||
register boolean inexact = FALSE;
|
||||
register boolean underflowtrap;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
left = *leftptr;
|
||||
right = *rightptr;
|
||||
|
||||
/* A zero "save" helps discover equal operands (for later), *
|
||||
* and is used in swapping operands (if needed). */
|
||||
Sgl_xortointp1(left,right,/*to*/save);
|
||||
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
|
||||
{
|
||||
if (Sgl_iszero_mantissa(left))
|
||||
{
|
||||
if (Sgl_isnotnan(right))
|
||||
{
|
||||
if (Sgl_isinfinity(right) && save!=0)
|
||||
{
|
||||
/*
|
||||
* invalid since operands are opposite signed infinity's
|
||||
*/
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(left))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(left);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Sgl_is_signalingnan(right))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(right);
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
} /* End left NaN or Infinity processing */
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(right))
|
||||
{
|
||||
if (Sgl_iszero_mantissa(right))
|
||||
{
|
||||
/* return infinity */
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(right))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(right);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
} /* End right NaN or Infinity processing */
|
||||
|
||||
/* Invariant: Must be dealing with finite numbers */
|
||||
|
||||
/* Compare operands by removing the sign */
|
||||
Sgl_copytoint_exponentmantissa(left,signless_upper_left);
|
||||
Sgl_copytoint_exponentmantissa(right,signless_upper_right);
|
||||
|
||||
/* sign difference selects add or sub operation. */
|
||||
if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
|
||||
{
|
||||
/* Set the left operand to the larger one by XOR swap *
|
||||
* First finish the first word using "save" */
|
||||
Sgl_xorfromintp1(save,right,/*to*/right);
|
||||
Sgl_xorfromintp1(save,left,/*to*/left);
|
||||
result_exponent = Sgl_exponent(left);
|
||||
}
|
||||
/* Invariant: left is not smaller than right. */
|
||||
|
||||
if((right_exponent = Sgl_exponent(right)) == 0)
|
||||
{
|
||||
/* Denormalized operands. First look for zeroes */
|
||||
if(Sgl_iszero_mantissa(right))
|
||||
{
|
||||
/* right is zero */
|
||||
if(Sgl_iszero_exponentmantissa(left))
|
||||
{
|
||||
/* Both operands are zeros */
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Sgl_or_signs(left,/*with*/right);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_and_signs(left,/*with*/right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left is not a zero and must be the result. Trapped
|
||||
* underflows are signaled if left is denormalized. Result
|
||||
* is always exact. */
|
||||
if( (result_exponent == 0) && Is_underflowtrap_enabled() )
|
||||
{
|
||||
/* need to normalize results mantissa */
|
||||
sign_save = Sgl_signextendedsign(left);
|
||||
Sgl_leftshiftby1(left);
|
||||
Sgl_normalize(left,result_exponent);
|
||||
Sgl_set_sign(left,/*using*/sign_save);
|
||||
Sgl_setwrapped_exponent(left,result_exponent,unfl);
|
||||
*dstptr = left;
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
}
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/* Neither are zeroes */
|
||||
Sgl_clear_sign(right); /* Exponent is already cleared */
|
||||
if(result_exponent == 0 )
|
||||
{
|
||||
/* Both operands are denormalized. The result must be exact
|
||||
* and is simply calculated. A sum could become normalized and a
|
||||
* difference could cancel to a true zero. */
|
||||
if( (/*signed*/int) save < 0 )
|
||||
{
|
||||
Sgl_subtract(left,/*minus*/right,/*into*/result);
|
||||
if(Sgl_iszero_mantissa(result))
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Sgl_setone_sign(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_setzero_sign(result);
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_addition(left,right,/*into*/result);
|
||||
if(Sgl_isone_hidden(result))
|
||||
{
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
/* need to normalize result */
|
||||
sign_save = Sgl_signextendedsign(result);
|
||||
Sgl_leftshiftby1(result);
|
||||
Sgl_normalize(result,result_exponent);
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Sgl_setwrapped_exponent(result,result_exponent,unfl);
|
||||
*dstptr = result;
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
right_exponent = 1; /* Set exponent to reflect different bias
|
||||
* with denomalized numbers. */
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_clear_signexponent_set_hidden(right);
|
||||
}
|
||||
Sgl_clear_exponent_set_hidden(left);
|
||||
diff_exponent = result_exponent - right_exponent;
|
||||
|
||||
/*
|
||||
* Special case alignment of operands that would force alignment
|
||||
* beyond the extent of the extension. A further optimization
|
||||
* could special case this but only reduces the path length for this
|
||||
* infrequent case.
|
||||
*/
|
||||
if(diff_exponent > SGL_THRESHOLD)
|
||||
{
|
||||
diff_exponent = SGL_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Align right operand by shifting to right */
|
||||
Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
|
||||
/*and lower to*/extent);
|
||||
|
||||
/* Treat sum and difference of the operands separately. */
|
||||
if( (/*signed*/int) save < 0 )
|
||||
{
|
||||
/*
|
||||
* Difference of the two operands. Their can be no overflow. A
|
||||
* borrow can occur out of the hidden bit and force a post
|
||||
* normalization phase.
|
||||
*/
|
||||
Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
|
||||
if(Sgl_iszero_hidden(result))
|
||||
{
|
||||
/* Handle normalization */
|
||||
/* A straight foward algorithm would now shift the result
|
||||
* and extension left until the hidden bit becomes one. Not
|
||||
* all of the extension bits need participate in the shift.
|
||||
* Only the two most significant bits (round and guard) are
|
||||
* needed. If only a single shift is needed then the guard
|
||||
* bit becomes a significant low order bit and the extension
|
||||
* must participate in the rounding. If more than a single
|
||||
* shift is needed, then all bits to the right of the guard
|
||||
* bit are zeros, and the guard bit may or may not be zero. */
|
||||
sign_save = Sgl_signextendedsign(result);
|
||||
Sgl_leftshiftby1_withextent(result,extent,result);
|
||||
|
||||
/* Need to check for a zero result. The sign and exponent
|
||||
* fields have already been zeroed. The more efficient test
|
||||
* of the full object can be used.
|
||||
*/
|
||||
if(Sgl_iszero(result))
|
||||
/* Must have been "x-x" or "x+(-x)". */
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
result_exponent--;
|
||||
/* Look to see if normalization is finished. */
|
||||
if(Sgl_isone_hidden(result))
|
||||
{
|
||||
if(result_exponent==0)
|
||||
{
|
||||
/* Denormalized, exponent should be zero. Left operand *
|
||||
* was normalized, so extent (guard, round) was zero */
|
||||
goto underflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No further normalization is needed. */
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Ext_leftshiftby1(extent);
|
||||
goto round;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for denormalized, exponent should be zero. Left *
|
||||
* operand was normalized, so extent (guard, round) was zero */
|
||||
if(!(underflowtrap = Is_underflowtrap_enabled()) &&
|
||||
result_exponent==0) goto underflow;
|
||||
|
||||
/* Shift extension to complete one bit of normalization and
|
||||
* update exponent. */
|
||||
Ext_leftshiftby1(extent);
|
||||
|
||||
/* Discover first one bit to determine shift amount. Use a
|
||||
* modified binary search. We have already shifted the result
|
||||
* one position right and still not found a one so the remainder
|
||||
* of the extension must be zero and simplifies rounding. */
|
||||
/* Scan bytes */
|
||||
while(Sgl_iszero_hiddenhigh7mantissa(result))
|
||||
{
|
||||
Sgl_leftshiftby8(result);
|
||||
if((result_exponent -= 8) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Now narrow it down to the nibble */
|
||||
if(Sgl_iszero_hiddenhigh3mantissa(result))
|
||||
{
|
||||
/* The lower nibble contains the normalizing one */
|
||||
Sgl_leftshiftby4(result);
|
||||
if((result_exponent -= 4) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Select case were first bit is set (already normalized)
|
||||
* otherwise select the proper shift. */
|
||||
if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
|
||||
{
|
||||
/* Already normalized */
|
||||
if(result_exponent <= 0) goto underflow;
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Sgl_set_exponent(result,/*using*/result_exponent);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_sethigh4bits(result,/*using*/sign_save);
|
||||
switch(jumpsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Sgl_leftshiftby3(result);
|
||||
result_exponent -= 3;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
Sgl_leftshiftby2(result);
|
||||
result_exponent -= 2;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
Sgl_leftshiftby1(result);
|
||||
result_exponent -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result_exponent > 0)
|
||||
{
|
||||
Sgl_set_exponent(result,/*using*/result_exponent);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION); /* Sign bit is already set */
|
||||
}
|
||||
/* Fixup potential underflows */
|
||||
underflow:
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
Sgl_set_sign(result,sign_save);
|
||||
Sgl_setwrapped_exponent(result,result_exponent,unfl);
|
||||
*dstptr = result;
|
||||
/* inexact = FALSE; */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Since we cannot get an inexact denormalized result,
|
||||
* we can now return.
|
||||
*/
|
||||
Sgl_right_align(result,/*by*/(1-result_exponent),extent);
|
||||
Sgl_clear_signexponent(result);
|
||||
Sgl_set_sign(result,sign_save);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
} /* end if(hidden...)... */
|
||||
/* Fall through and round */
|
||||
} /* end if(save < 0)... */
|
||||
else
|
||||
{
|
||||
/* Add magnitudes */
|
||||
Sgl_addition(left,right,/*to*/result);
|
||||
if(Sgl_isone_hiddenoverflow(result))
|
||||
{
|
||||
/* Prenormalization required. */
|
||||
Sgl_rightshiftby1_withextent(result,extent,extent);
|
||||
Sgl_arithrightshiftby1(result);
|
||||
result_exponent++;
|
||||
} /* end if hiddenoverflow... */
|
||||
} /* end else ...add magnitudes... */
|
||||
|
||||
/* Round the result. If the extension is all zeros,then the result is
|
||||
* exact. Otherwise round in the correct direction. No underflow is
|
||||
* possible. If a postnormalization is necessary, then the mantissa is
|
||||
* all zeros so no shift is needed. */
|
||||
round:
|
||||
if(Ext_isnotzero(extent))
|
||||
{
|
||||
inexact = TRUE;
|
||||
switch(Rounding_mode())
|
||||
{
|
||||
case ROUNDNEAREST: /* The default. */
|
||||
if(Ext_isone_sign(extent))
|
||||
{
|
||||
/* at least 1/2 ulp */
|
||||
if(Ext_isnotzero_lower(extent) ||
|
||||
Sgl_isone_lowmantissa(result))
|
||||
{
|
||||
/* either exactly half way and odd or more than 1/2ulp */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDPLUS:
|
||||
if(Sgl_iszero_sign(result))
|
||||
{
|
||||
/* Round up positive results */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDMINUS:
|
||||
if(Sgl_isone_sign(result))
|
||||
{
|
||||
/* Round down negative results */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
|
||||
case ROUNDZERO:;
|
||||
/* truncate is simple */
|
||||
} /* end switch... */
|
||||
if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
|
||||
}
|
||||
if(result_exponent == SGL_INFINITY_EXPONENT)
|
||||
{
|
||||
/* Overflow */
|
||||
if(Is_overflowtrap_enabled())
|
||||
{
|
||||
Sgl_setwrapped_exponent(result,result_exponent,ovfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_overflowflag();
|
||||
inexact = TRUE;
|
||||
Sgl_setoverflow(result);
|
||||
}
|
||||
}
|
||||
else Sgl_set_exponent(result,result_exponent);
|
||||
*dstptr = result;
|
||||
if(inexact)
|
||||
if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(NOEXCEPTION);
|
||||
}
|
155
arch/parisc/math-emu/sfcmp.c
Обычный файл
155
arch/parisc/math-emu/sfcmp.c
Обычный файл
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfcmp.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* sgl_cmp: compare two values
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fcmp(leftptr, rightptr, cond, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* sgl_cmp: compare two values
|
||||
*/
|
||||
int
|
||||
sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
|
||||
unsigned int cond, unsigned int *status)
|
||||
|
||||
/* The predicate to be tested */
|
||||
|
||||
{
|
||||
register unsigned int left, right;
|
||||
register int xorresult;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
left = *leftptr;
|
||||
right = *rightptr;
|
||||
|
||||
/*
|
||||
* Test for NaN
|
||||
*/
|
||||
if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
|
||||
|| (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) )
|
||||
{
|
||||
/* Check if a NaN is involved. Signal an invalid exception when
|
||||
* comparing a signaling NaN or when comparing quiet NaNs and the
|
||||
* low bit of the condition is set */
|
||||
if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
|
||||
&& Sgl_isnotzero_mantissa(left)
|
||||
&& (Exception(cond) || Sgl_isone_signaling(left)))
|
||||
||
|
||||
( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
|
||||
&& Sgl_isnotzero_mantissa(right)
|
||||
&& (Exception(cond) || Sgl_isone_signaling(right)) ) )
|
||||
{
|
||||
if( Is_invalidtrap_enabled() ) {
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(INVALIDEXCEPTION);
|
||||
}
|
||||
else Set_invalidflag();
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* All the exceptional conditions are handled, now special case
|
||||
NaN compares */
|
||||
else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
|
||||
&& Sgl_isnotzero_mantissa(left))
|
||||
||
|
||||
((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
|
||||
&& Sgl_isnotzero_mantissa(right)) )
|
||||
{
|
||||
/* NaNs always compare unordered. */
|
||||
Set_status_cbit(Unordered(cond));
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* infinities will drop down to the normal compare mechanisms */
|
||||
}
|
||||
/* First compare for unequal signs => less or greater or
|
||||
* special equal case */
|
||||
Sgl_xortointp1(left,right,xorresult);
|
||||
if( xorresult < 0 )
|
||||
{
|
||||
/* left negative => less, left positive => greater.
|
||||
* equal is possible if both operands are zeros. */
|
||||
if( Sgl_iszero_exponentmantissa(left)
|
||||
&& Sgl_iszero_exponentmantissa(right) )
|
||||
{
|
||||
Set_status_cbit(Equal(cond));
|
||||
}
|
||||
else if( Sgl_isone_sign(left) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
/* Signs are the same. Treat negative numbers separately
|
||||
* from the positives because of the reversed sense. */
|
||||
else if( Sgl_all(left) == Sgl_all(right) )
|
||||
{
|
||||
Set_status_cbit(Equal(cond));
|
||||
}
|
||||
else if( Sgl_iszero_sign(left) )
|
||||
{
|
||||
/* Positive compare */
|
||||
if( Sgl_all(left) < Sgl_all(right) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Negative compare. Signed or unsigned compares
|
||||
* both work the same. That distinction is only
|
||||
* important when the sign bits differ. */
|
||||
if( Sgl_all(left) > Sgl_all(right) )
|
||||
{
|
||||
Set_status_cbit(Lessthan(cond));
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_status_cbit(Greaterthan(cond));
|
||||
}
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
392
arch/parisc/math-emu/sfdiv.c
Обычный файл
392
arch/parisc/math-emu/sfdiv.c
Обычный файл
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfdiv.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Precision Floating-point Divide
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fdiv(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single Precision Floating-point Divide
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
|
||||
sgl_floating_point * dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1, opnd2, opnd3, result;
|
||||
register int dest_exponent, count;
|
||||
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
|
||||
boolean is_tiny;
|
||||
|
||||
opnd1 = *srcptr1;
|
||||
opnd2 = *srcptr2;
|
||||
/*
|
||||
* set sign bit of result
|
||||
*/
|
||||
if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
|
||||
else Sgl_setzero(result);
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(opnd1)) {
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
if (Sgl_isnotnan(opnd2)) {
|
||||
if (Sgl_isinfinity(opnd2)) {
|
||||
/*
|
||||
* invalid since both operands
|
||||
* are infinity
|
||||
*/
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Sgl_setinfinity_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Sgl_is_signalingnan(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd1;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(opnd2)) {
|
||||
if (Sgl_iszero_mantissa(opnd2)) {
|
||||
/*
|
||||
* return zero
|
||||
*/
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* check for division by zero
|
||||
*/
|
||||
if (Sgl_iszero_exponentmantissa(opnd2)) {
|
||||
if (Sgl_iszero_exponentmantissa(opnd1)) {
|
||||
/* invalid since both operands are zero */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
if (Is_divisionbyzerotrap_enabled())
|
||||
return(DIVISIONBYZEROEXCEPTION);
|
||||
Set_divisionbyzeroflag();
|
||||
Sgl_setinfinity_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent
|
||||
*/
|
||||
dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Generate mantissa
|
||||
*/
|
||||
if (Sgl_isnotzero_exponent(opnd1)) {
|
||||
/* set hidden bit */
|
||||
Sgl_clear_signexponent_set_hidden(opnd1);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized; want to normalize */
|
||||
Sgl_clear_signexponent(opnd1);
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
Sgl_normalize(opnd1,dest_exponent);
|
||||
}
|
||||
/* opnd2 needs to have hidden bit set with msb in hidden bit */
|
||||
if (Sgl_isnotzero_exponent(opnd2)) {
|
||||
Sgl_clear_signexponent_set_hidden(opnd2);
|
||||
}
|
||||
else {
|
||||
/* is denormalized; want to normalize */
|
||||
Sgl_clear_signexponent(opnd2);
|
||||
Sgl_leftshiftby1(opnd2);
|
||||
while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
|
||||
Sgl_leftshiftby8(opnd2);
|
||||
dest_exponent += 8;
|
||||
}
|
||||
if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
|
||||
Sgl_leftshiftby4(opnd2);
|
||||
dest_exponent += 4;
|
||||
}
|
||||
while(Sgl_iszero_hidden(opnd2)) {
|
||||
Sgl_leftshiftby1(opnd2);
|
||||
dest_exponent += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Divide the source mantissas */
|
||||
|
||||
/*
|
||||
* A non_restoring divide algorithm is used.
|
||||
*/
|
||||
Sgl_subtract(opnd1,opnd2,opnd1);
|
||||
Sgl_setzero(opnd3);
|
||||
for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
if (Sgl_iszero_sign(opnd1)) {
|
||||
Sgl_setone_lowmantissa(opnd3);
|
||||
Sgl_subtract(opnd1,opnd2,opnd1);
|
||||
}
|
||||
else Sgl_addition(opnd1,opnd2,opnd1);
|
||||
}
|
||||
if (count <= SGL_P) {
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
Sgl_setone_lowmantissa(opnd3);
|
||||
Sgl_leftshift(opnd3,SGL_P-count);
|
||||
if (Sgl_iszero_hidden(opnd3)) {
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
dest_exponent--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Sgl_iszero_hidden(opnd3)) {
|
||||
/* need to get one more bit of result */
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
if (Sgl_iszero_sign(opnd1)) {
|
||||
Sgl_setone_lowmantissa(opnd3);
|
||||
Sgl_subtract(opnd1,opnd2,opnd1);
|
||||
}
|
||||
else Sgl_addition(opnd1,opnd2,opnd1);
|
||||
dest_exponent--;
|
||||
}
|
||||
if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
|
||||
stickybit = Sgl_all(opnd1);
|
||||
}
|
||||
inexact = guardbit | stickybit;
|
||||
|
||||
/*
|
||||
* round result
|
||||
*/
|
||||
if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
|
||||
Sgl_clear_signexponent(opnd3);
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result))
|
||||
Sgl_increment_mantissa(opnd3);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result))
|
||||
Sgl_increment_mantissa(opnd3);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit) {
|
||||
if (stickybit || Sgl_isone_lowmantissa(opnd3))
|
||||
Sgl_increment_mantissa(opnd3);
|
||||
}
|
||||
}
|
||||
if (Sgl_isone_hidden(opnd3)) dest_exponent++;
|
||||
}
|
||||
Sgl_set_mantissa(result,opnd3);
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (dest_exponent >= SGL_INFINITY_EXPONENT) {
|
||||
/* trap if OVERFLOWTRAP enabled */
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
Set_overflowflag();
|
||||
/* set result to infinity or largest number */
|
||||
Sgl_setoverflow(result);
|
||||
inexact = TRUE;
|
||||
}
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
else if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,unfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
|
||||
/* Determine if should set underflow flag */
|
||||
is_tiny = TRUE;
|
||||
if (dest_exponent == 0 && inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Sgl_isone_lowmantissa(opnd3))) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
stickybit = inexact;
|
||||
Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
|
||||
|
||||
/* return rounded number */
|
||||
if (inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Sgl_isone_lowmantissa(opnd3))) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_tiny) Set_underflowflag();
|
||||
}
|
||||
Sgl_set_exponentmantissa(result,opnd3);
|
||||
}
|
||||
else Sgl_set_exponent(result,dest_exponent);
|
||||
*dstptr = result;
|
||||
/* check for inexact */
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
380
arch/parisc/math-emu/sfmpy.c
Обычный файл
380
arch/parisc/math-emu/sfmpy.c
Обычный файл
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfmpy.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Precision Floating-point Multiply
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fmpy(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single Precision Floating-point Multiply
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_fmpy(
|
||||
sgl_floating_point *srcptr1,
|
||||
sgl_floating_point *srcptr2,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1, opnd2, opnd3, result;
|
||||
register int dest_exponent, count;
|
||||
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
|
||||
boolean is_tiny;
|
||||
|
||||
opnd1 = *srcptr1;
|
||||
opnd2 = *srcptr2;
|
||||
/*
|
||||
* set sign bit of result
|
||||
*/
|
||||
if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);
|
||||
else Sgl_setzero(result);
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(opnd1)) {
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
if (Sgl_isnotnan(opnd2)) {
|
||||
if (Sgl_iszero_exponentmantissa(opnd2)) {
|
||||
/*
|
||||
* invalid since operands are infinity
|
||||
* and zero
|
||||
*/
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Sgl_setinfinity_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Sgl_is_signalingnan(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd1;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(opnd2)) {
|
||||
if (Sgl_iszero_mantissa(opnd2)) {
|
||||
if (Sgl_iszero_exponentmantissa(opnd1)) {
|
||||
/* invalid since operands are zero & infinity */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(opnd2);
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
Sgl_setinfinity_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Generate exponent
|
||||
*/
|
||||
dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
|
||||
|
||||
/*
|
||||
* Generate mantissa
|
||||
*/
|
||||
if (Sgl_isnotzero_exponent(opnd1)) {
|
||||
/* set hidden bit */
|
||||
Sgl_clear_signexponent_set_hidden(opnd1);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized, adjust exponent */
|
||||
Sgl_clear_signexponent(opnd1);
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
Sgl_normalize(opnd1,dest_exponent);
|
||||
}
|
||||
/* opnd2 needs to have hidden bit set with msb in hidden bit */
|
||||
if (Sgl_isnotzero_exponent(opnd2)) {
|
||||
Sgl_clear_signexponent_set_hidden(opnd2);
|
||||
}
|
||||
else {
|
||||
/* check for zero */
|
||||
if (Sgl_iszero_mantissa(opnd2)) {
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* is denormalized; want to normalize */
|
||||
Sgl_clear_signexponent(opnd2);
|
||||
Sgl_leftshiftby1(opnd2);
|
||||
Sgl_normalize(opnd2,dest_exponent);
|
||||
}
|
||||
|
||||
/* Multiply two source mantissas together */
|
||||
|
||||
Sgl_leftshiftby4(opnd2); /* make room for guard bits */
|
||||
Sgl_setzero(opnd3);
|
||||
/*
|
||||
* Four bits at a time are inspected in each loop, and a
|
||||
* simple shift and add multiply algorithm is used.
|
||||
*/
|
||||
for (count=1;count<SGL_P;count+=4) {
|
||||
stickybit |= Slow4(opnd3);
|
||||
Sgl_rightshiftby4(opnd3);
|
||||
if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
|
||||
if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
|
||||
if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
|
||||
if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
|
||||
Sgl_rightshiftby4(opnd1);
|
||||
}
|
||||
/* make sure result is left-justified */
|
||||
if (Sgl_iszero_sign(opnd3)) {
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
}
|
||||
else {
|
||||
/* result mantissa >= 2. */
|
||||
dest_exponent++;
|
||||
}
|
||||
/* check for denormalized result */
|
||||
while (Sgl_iszero_sign(opnd3)) {
|
||||
Sgl_leftshiftby1(opnd3);
|
||||
dest_exponent--;
|
||||
}
|
||||
/*
|
||||
* check for guard, sticky and inexact bits
|
||||
*/
|
||||
stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
|
||||
guardbit = Sbit24(opnd3);
|
||||
inexact = guardbit | stickybit;
|
||||
|
||||
/* re-align mantissa */
|
||||
Sgl_rightshiftby8(opnd3);
|
||||
|
||||
/*
|
||||
* round result
|
||||
*/
|
||||
if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
|
||||
Sgl_clear_signexponent(opnd3);
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result))
|
||||
Sgl_increment(opnd3);
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result))
|
||||
Sgl_increment(opnd3);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit) {
|
||||
if (stickybit || Sgl_isone_lowmantissa(opnd3))
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
}
|
||||
if (Sgl_isone_hidden(opnd3)) dest_exponent++;
|
||||
}
|
||||
Sgl_set_mantissa(result,opnd3);
|
||||
|
||||
/*
|
||||
* Test for overflow
|
||||
*/
|
||||
if (dest_exponent >= SGL_INFINITY_EXPONENT) {
|
||||
/* trap if OVERFLOWTRAP enabled */
|
||||
if (Is_overflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
inexact = TRUE;
|
||||
Set_overflowflag();
|
||||
/* set result to infinity or largest number */
|
||||
Sgl_setoverflow(result);
|
||||
}
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
else if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,unfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
|
||||
/* Determine if should set underflow flag */
|
||||
is_tiny = TRUE;
|
||||
if (dest_exponent == 0 && inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Sgl_isone_lowmantissa(opnd3))) {
|
||||
Sgl_increment(opnd3);
|
||||
if (Sgl_isone_hiddenoverflow(opnd3))
|
||||
is_tiny = FALSE;
|
||||
Sgl_decrement(opnd3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
stickybit = inexact;
|
||||
Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
|
||||
|
||||
/* return zero or smallest number */
|
||||
if (inexact) {
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
if (Sgl_iszero_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDMINUS:
|
||||
if (Sgl_isone_sign(result)) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
if (guardbit && (stickybit ||
|
||||
Sgl_isone_lowmantissa(opnd3))) {
|
||||
Sgl_increment(opnd3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_tiny) Set_underflowflag();
|
||||
}
|
||||
Sgl_set_exponentmantissa(result,opnd3);
|
||||
}
|
||||
else Sgl_set_exponent(result,dest_exponent);
|
||||
*dstptr = result;
|
||||
|
||||
/* check for inexact */
|
||||
if (inexact) {
|
||||
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
}
|
||||
return(NOEXCEPTION);
|
||||
}
|
290
arch/parisc/math-emu/sfrem.c
Обычный файл
290
arch/parisc/math-emu/sfrem.c
Обычный файл
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfrem.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Precision Floating-point Remainder
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_frem(srcptr1,srcptr2,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single Precision Floating-point Remainder
|
||||
*/
|
||||
|
||||
int
|
||||
sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
|
||||
sgl_floating_point * dstptr, unsigned int *status)
|
||||
{
|
||||
register unsigned int opnd1, opnd2, result;
|
||||
register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
|
||||
register boolean roundup = FALSE;
|
||||
|
||||
opnd1 = *srcptr1;
|
||||
opnd2 = *srcptr2;
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
if (Sgl_isnotnan(opnd2)) {
|
||||
/* invalid since first operand is infinity */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd1)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd1);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Sgl_is_signalingnan(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled())
|
||||
return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd1;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
|
||||
if (Sgl_iszero_mantissa(opnd2)) {
|
||||
/*
|
||||
* return first operand
|
||||
*/
|
||||
*dstptr = opnd1;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(opnd2)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(opnd2);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = opnd2;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* check second operand for zero
|
||||
*/
|
||||
if (Sgl_iszero_exponentmantissa(opnd2)) {
|
||||
/* invalid since second operand is zero */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* get sign of result
|
||||
*/
|
||||
result = opnd1;
|
||||
|
||||
/*
|
||||
* check for denormalized operands
|
||||
*/
|
||||
if (opnd1_exponent == 0) {
|
||||
/* check for zero */
|
||||
if (Sgl_iszero_mantissa(opnd1)) {
|
||||
*dstptr = opnd1;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* normalize, then continue */
|
||||
opnd1_exponent = 1;
|
||||
Sgl_normalize(opnd1,opnd1_exponent);
|
||||
}
|
||||
else {
|
||||
Sgl_clear_signexponent_set_hidden(opnd1);
|
||||
}
|
||||
if (opnd2_exponent == 0) {
|
||||
/* normalize, then continue */
|
||||
opnd2_exponent = 1;
|
||||
Sgl_normalize(opnd2,opnd2_exponent);
|
||||
}
|
||||
else {
|
||||
Sgl_clear_signexponent_set_hidden(opnd2);
|
||||
}
|
||||
|
||||
/* find result exponent and divide step loop count */
|
||||
dest_exponent = opnd2_exponent - 1;
|
||||
stepcount = opnd1_exponent - opnd2_exponent;
|
||||
|
||||
/*
|
||||
* check for opnd1/opnd2 < 1
|
||||
*/
|
||||
if (stepcount < 0) {
|
||||
/*
|
||||
* check for opnd1/opnd2 > 1/2
|
||||
*
|
||||
* In this case n will round to 1, so
|
||||
* r = opnd1 - opnd2
|
||||
*/
|
||||
if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
|
||||
Sgl_all(result) = ~Sgl_all(result); /* set sign */
|
||||
/* align opnd2 with opnd1 */
|
||||
Sgl_leftshiftby1(opnd2);
|
||||
Sgl_subtract(opnd2,opnd1,opnd2);
|
||||
/* now normalize */
|
||||
while (Sgl_iszero_hidden(opnd2)) {
|
||||
Sgl_leftshiftby1(opnd2);
|
||||
dest_exponent--;
|
||||
}
|
||||
Sgl_set_exponentmantissa(result,opnd2);
|
||||
goto testforunderflow;
|
||||
}
|
||||
/*
|
||||
* opnd1/opnd2 <= 1/2
|
||||
*
|
||||
* In this case n will round to zero, so
|
||||
* r = opnd1
|
||||
*/
|
||||
Sgl_set_exponentmantissa(result,opnd1);
|
||||
dest_exponent = opnd1_exponent;
|
||||
goto testforunderflow;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*
|
||||
* Do iterative subtract until remainder is less than operand 2.
|
||||
*/
|
||||
while (stepcount-- > 0 && Sgl_all(opnd1)) {
|
||||
if (Sgl_isnotlessthan(opnd1,opnd2))
|
||||
Sgl_subtract(opnd1,opnd2,opnd1);
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
}
|
||||
/*
|
||||
* Do last subtract, then determine which way to round if remainder
|
||||
* is exactly 1/2 of opnd2
|
||||
*/
|
||||
if (Sgl_isnotlessthan(opnd1,opnd2)) {
|
||||
Sgl_subtract(opnd1,opnd2,opnd1);
|
||||
roundup = TRUE;
|
||||
}
|
||||
if (stepcount > 0 || Sgl_iszero(opnd1)) {
|
||||
/* division is exact, remainder is zero */
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for cases where opnd1/opnd2 < n
|
||||
*
|
||||
* In this case the result's sign will be opposite that of
|
||||
* opnd1. The mantissa also needs some correction.
|
||||
*/
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
if (Sgl_isgreaterthan(opnd1,opnd2)) {
|
||||
Sgl_invert_sign(result);
|
||||
Sgl_subtract((opnd2<<1),opnd1,opnd1);
|
||||
}
|
||||
/* check for remainder being exactly 1/2 of opnd2 */
|
||||
else if (Sgl_isequal(opnd1,opnd2) && roundup) {
|
||||
Sgl_invert_sign(result);
|
||||
}
|
||||
|
||||
/* normalize result's mantissa */
|
||||
while (Sgl_iszero_hidden(opnd1)) {
|
||||
dest_exponent--;
|
||||
Sgl_leftshiftby1(opnd1);
|
||||
}
|
||||
Sgl_set_exponentmantissa(result,opnd1);
|
||||
|
||||
/*
|
||||
* Test for underflow
|
||||
*/
|
||||
testforunderflow:
|
||||
if (dest_exponent <= 0) {
|
||||
/* trap if UNDERFLOWTRAP enabled */
|
||||
if (Is_underflowtrap_enabled()) {
|
||||
/*
|
||||
* Adjust bias of result
|
||||
*/
|
||||
Sgl_setwrapped_exponent(result,dest_exponent,unfl);
|
||||
*dstptr = result;
|
||||
/* frem is always exact */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* denormalize result or set to signed zero
|
||||
*/
|
||||
if (dest_exponent >= (1 - SGL_P)) {
|
||||
Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
|
||||
}
|
||||
else {
|
||||
Sgl_setzero_exponentmantissa(result);
|
||||
}
|
||||
}
|
||||
else Sgl_set_exponent(result,dest_exponent);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
187
arch/parisc/math-emu/sfsqrt.c
Обычный файл
187
arch/parisc/math-emu/sfsqrt.c
Обычный файл
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single Floating-point Square Root
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fsqrt(srcptr,nullptr,dstptr,status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single Floating-point Square Root
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
unsigned int
|
||||
sgl_fsqrt(
|
||||
sgl_floating_point *srcptr,
|
||||
unsigned int *nullptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int src, result;
|
||||
register int src_exponent;
|
||||
register unsigned int newbit, sum;
|
||||
register boolean guardbit = FALSE, even_exponent;
|
||||
|
||||
src = *srcptr;
|
||||
/*
|
||||
* check source operand for NaN or infinity
|
||||
*/
|
||||
if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
|
||||
/*
|
||||
* is signaling NaN?
|
||||
*/
|
||||
if (Sgl_isone_signaling(src)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(src);
|
||||
}
|
||||
/*
|
||||
* Return quiet NaN or positive infinity.
|
||||
* Fall thru to negative test if negative infinity.
|
||||
*/
|
||||
if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
|
||||
*dstptr = src;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check for zero source operand
|
||||
*/
|
||||
if (Sgl_iszero_exponentmantissa(src)) {
|
||||
*dstptr = src;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* check for negative source operand
|
||||
*/
|
||||
if (Sgl_isone_sign(src)) {
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(src);
|
||||
*dstptr = src;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate result
|
||||
*/
|
||||
if (src_exponent > 0) {
|
||||
even_exponent = Sgl_hidden(src);
|
||||
Sgl_clear_signexponent_set_hidden(src);
|
||||
}
|
||||
else {
|
||||
/* normalize operand */
|
||||
Sgl_clear_signexponent(src);
|
||||
src_exponent++;
|
||||
Sgl_normalize(src,src_exponent);
|
||||
even_exponent = src_exponent & 1;
|
||||
}
|
||||
if (even_exponent) {
|
||||
/* exponent is even */
|
||||
/* Add comment here. Explain why odd exponent needs correction */
|
||||
Sgl_leftshiftby1(src);
|
||||
}
|
||||
/*
|
||||
* Add comment here. Explain following algorithm.
|
||||
*
|
||||
* Trust me, it works.
|
||||
*
|
||||
*/
|
||||
Sgl_setzero(result);
|
||||
newbit = 1 << SGL_P;
|
||||
while (newbit && Sgl_isnotzero(src)) {
|
||||
Sgl_addition(result,newbit,sum);
|
||||
if(sum <= Sgl_all(src)) {
|
||||
/* update result */
|
||||
Sgl_addition(result,(newbit<<1),result);
|
||||
Sgl_subtract(src,sum,src);
|
||||
}
|
||||
Sgl_rightshiftby1(newbit);
|
||||
Sgl_leftshiftby1(src);
|
||||
}
|
||||
/* correct exponent for pre-shift */
|
||||
if (even_exponent) {
|
||||
Sgl_rightshiftby1(result);
|
||||
}
|
||||
|
||||
/* check for inexact */
|
||||
if (Sgl_isnotzero(src)) {
|
||||
if (!even_exponent && Sgl_islessthan(result,src))
|
||||
Sgl_increment(result);
|
||||
guardbit = Sgl_lowmantissa(result);
|
||||
Sgl_rightshiftby1(result);
|
||||
|
||||
/* now round result */
|
||||
switch (Rounding_mode()) {
|
||||
case ROUNDPLUS:
|
||||
Sgl_increment(result);
|
||||
break;
|
||||
case ROUNDNEAREST:
|
||||
/* stickybit is always true, so guardbit
|
||||
* is enough to determine rounding */
|
||||
if (guardbit) {
|
||||
Sgl_increment(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* increment result exponent by 1 if mantissa overflowed */
|
||||
if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2;
|
||||
|
||||
if (Is_inexacttrap_enabled()) {
|
||||
Sgl_set_exponent(result,
|
||||
((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
|
||||
*dstptr = result;
|
||||
return(INEXACTEXCEPTION);
|
||||
}
|
||||
else Set_inexactflag();
|
||||
}
|
||||
else {
|
||||
Sgl_rightshiftby1(result);
|
||||
}
|
||||
Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
521
arch/parisc/math-emu/sfsub.c
Обычный файл
521
arch/parisc/math-emu/sfsub.c
Обычный файл
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* BEGIN_DESC
|
||||
*
|
||||
* File:
|
||||
* @(#) pa/spmath/sfsub.c $Revision: 1.1 $
|
||||
*
|
||||
* Purpose:
|
||||
* Single_subtract: subtract two single precision values.
|
||||
*
|
||||
* External Interfaces:
|
||||
* sgl_fsub(leftptr, rightptr, dstptr, status)
|
||||
*
|
||||
* Internal Interfaces:
|
||||
*
|
||||
* Theory:
|
||||
* <<please update with a overview of the operation of this file>>
|
||||
*
|
||||
* END_DESC
|
||||
*/
|
||||
|
||||
|
||||
#include "float.h"
|
||||
#include "sgl_float.h"
|
||||
|
||||
/*
|
||||
* Single_subtract: subtract two single precision values.
|
||||
*/
|
||||
int
|
||||
sgl_fsub(
|
||||
sgl_floating_point *leftptr,
|
||||
sgl_floating_point *rightptr,
|
||||
sgl_floating_point *dstptr,
|
||||
unsigned int *status)
|
||||
{
|
||||
register unsigned int left, right, result, extent;
|
||||
register unsigned int signless_upper_left, signless_upper_right, save;
|
||||
|
||||
register int result_exponent, right_exponent, diff_exponent;
|
||||
register int sign_save, jumpsize;
|
||||
register boolean inexact = FALSE, underflowtrap;
|
||||
|
||||
/* Create local copies of the numbers */
|
||||
left = *leftptr;
|
||||
right = *rightptr;
|
||||
|
||||
/* A zero "save" helps discover equal operands (for later), *
|
||||
* and is used in swapping operands (if needed). */
|
||||
Sgl_xortointp1(left,right,/*to*/save);
|
||||
|
||||
/*
|
||||
* check first operand for NaN's or infinity
|
||||
*/
|
||||
if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
|
||||
{
|
||||
if (Sgl_iszero_mantissa(left))
|
||||
{
|
||||
if (Sgl_isnotnan(right))
|
||||
{
|
||||
if (Sgl_isinfinity(right) && save==0)
|
||||
{
|
||||
/*
|
||||
* invalid since operands are same signed infinity's
|
||||
*/
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
Set_invalidflag();
|
||||
Sgl_makequietnan(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return infinity
|
||||
*/
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(left))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(left);
|
||||
}
|
||||
/*
|
||||
* is second operand a signaling NaN?
|
||||
*/
|
||||
else if (Sgl_is_signalingnan(right))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(right);
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
} /* End left NaN or Infinity processing */
|
||||
/*
|
||||
* check second operand for NaN's or infinity
|
||||
*/
|
||||
if (Sgl_isinfinity_exponent(right))
|
||||
{
|
||||
if (Sgl_iszero_mantissa(right))
|
||||
{
|
||||
/* return infinity */
|
||||
Sgl_invert_sign(right);
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* is NaN; signaling or quiet?
|
||||
*/
|
||||
if (Sgl_isone_signaling(right))
|
||||
{
|
||||
/* trap if INVALIDTRAP enabled */
|
||||
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
|
||||
/* make NaN quiet */
|
||||
Set_invalidflag();
|
||||
Sgl_set_quiet(right);
|
||||
}
|
||||
/*
|
||||
* return quiet NaN
|
||||
*/
|
||||
*dstptr = right;
|
||||
return(NOEXCEPTION);
|
||||
} /* End right NaN or Infinity processing */
|
||||
|
||||
/* Invariant: Must be dealing with finite numbers */
|
||||
|
||||
/* Compare operands by removing the sign */
|
||||
Sgl_copytoint_exponentmantissa(left,signless_upper_left);
|
||||
Sgl_copytoint_exponentmantissa(right,signless_upper_right);
|
||||
|
||||
/* sign difference selects sub or add operation. */
|
||||
if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
|
||||
{
|
||||
/* Set the left operand to the larger one by XOR swap *
|
||||
* First finish the first word using "save" */
|
||||
Sgl_xorfromintp1(save,right,/*to*/right);
|
||||
Sgl_xorfromintp1(save,left,/*to*/left);
|
||||
result_exponent = Sgl_exponent(left);
|
||||
Sgl_invert_sign(left);
|
||||
}
|
||||
/* Invariant: left is not smaller than right. */
|
||||
|
||||
if((right_exponent = Sgl_exponent(right)) == 0)
|
||||
{
|
||||
/* Denormalized operands. First look for zeroes */
|
||||
if(Sgl_iszero_mantissa(right))
|
||||
{
|
||||
/* right is zero */
|
||||
if(Sgl_iszero_exponentmantissa(left))
|
||||
{
|
||||
/* Both operands are zeros */
|
||||
Sgl_invert_sign(right);
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Sgl_or_signs(left,/*with*/right);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_and_signs(left,/*with*/right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left is not a zero and must be the result. Trapped
|
||||
* underflows are signaled if left is denormalized. Result
|
||||
* is always exact. */
|
||||
if( (result_exponent == 0) && Is_underflowtrap_enabled() )
|
||||
{
|
||||
/* need to normalize results mantissa */
|
||||
sign_save = Sgl_signextendedsign(left);
|
||||
Sgl_leftshiftby1(left);
|
||||
Sgl_normalize(left,result_exponent);
|
||||
Sgl_set_sign(left,/*using*/sign_save);
|
||||
Sgl_setwrapped_exponent(left,result_exponent,unfl);
|
||||
*dstptr = left;
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
}
|
||||
*dstptr = left;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
|
||||
/* Neither are zeroes */
|
||||
Sgl_clear_sign(right); /* Exponent is already cleared */
|
||||
if(result_exponent == 0 )
|
||||
{
|
||||
/* Both operands are denormalized. The result must be exact
|
||||
* and is simply calculated. A sum could become normalized and a
|
||||
* difference could cancel to a true zero. */
|
||||
if( (/*signed*/int) save >= 0 )
|
||||
{
|
||||
Sgl_subtract(left,/*minus*/right,/*into*/result);
|
||||
if(Sgl_iszero_mantissa(result))
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS))
|
||||
{
|
||||
Sgl_setone_sign(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_setzero_sign(result);
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_addition(left,right,/*into*/result);
|
||||
if(Sgl_isone_hidden(result))
|
||||
{
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
}
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
/* need to normalize result */
|
||||
sign_save = Sgl_signextendedsign(result);
|
||||
Sgl_leftshiftby1(result);
|
||||
Sgl_normalize(result,result_exponent);
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Sgl_setwrapped_exponent(result,result_exponent,unfl);
|
||||
*dstptr = result;
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
right_exponent = 1; /* Set exponent to reflect different bias
|
||||
* with denomalized numbers. */
|
||||
}
|
||||
else
|
||||
{
|
||||
Sgl_clear_signexponent_set_hidden(right);
|
||||
}
|
||||
Sgl_clear_exponent_set_hidden(left);
|
||||
diff_exponent = result_exponent - right_exponent;
|
||||
|
||||
/*
|
||||
* Special case alignment of operands that would force alignment
|
||||
* beyond the extent of the extension. A further optimization
|
||||
* could special case this but only reduces the path length for this
|
||||
* infrequent case.
|
||||
*/
|
||||
if(diff_exponent > SGL_THRESHOLD)
|
||||
{
|
||||
diff_exponent = SGL_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Align right operand by shifting to right */
|
||||
Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
|
||||
/*and lower to*/extent);
|
||||
|
||||
/* Treat sum and difference of the operands separately. */
|
||||
if( (/*signed*/int) save >= 0 )
|
||||
{
|
||||
/*
|
||||
* Difference of the two operands. Their can be no overflow. A
|
||||
* borrow can occur out of the hidden bit and force a post
|
||||
* normalization phase.
|
||||
*/
|
||||
Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
|
||||
if(Sgl_iszero_hidden(result))
|
||||
{
|
||||
/* Handle normalization */
|
||||
/* A straight foward algorithm would now shift the result
|
||||
* and extension left until the hidden bit becomes one. Not
|
||||
* all of the extension bits need participate in the shift.
|
||||
* Only the two most significant bits (round and guard) are
|
||||
* needed. If only a single shift is needed then the guard
|
||||
* bit becomes a significant low order bit and the extension
|
||||
* must participate in the rounding. If more than a single
|
||||
* shift is needed, then all bits to the right of the guard
|
||||
* bit are zeros, and the guard bit may or may not be zero. */
|
||||
sign_save = Sgl_signextendedsign(result);
|
||||
Sgl_leftshiftby1_withextent(result,extent,result);
|
||||
|
||||
/* Need to check for a zero result. The sign and exponent
|
||||
* fields have already been zeroed. The more efficient test
|
||||
* of the full object can be used.
|
||||
*/
|
||||
if(Sgl_iszero(result))
|
||||
/* Must have been "x-x" or "x+(-x)". */
|
||||
{
|
||||
if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
result_exponent--;
|
||||
/* Look to see if normalization is finished. */
|
||||
if(Sgl_isone_hidden(result))
|
||||
{
|
||||
if(result_exponent==0)
|
||||
{
|
||||
/* Denormalized, exponent should be zero. Left operand *
|
||||
* was normalized, so extent (guard, round) was zero */
|
||||
goto underflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No further normalization is needed. */
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Ext_leftshiftby1(extent);
|
||||
goto round;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for denormalized, exponent should be zero. Left *
|
||||
* operand was normalized, so extent (guard, round) was zero */
|
||||
if(!(underflowtrap = Is_underflowtrap_enabled()) &&
|
||||
result_exponent==0) goto underflow;
|
||||
|
||||
/* Shift extension to complete one bit of normalization and
|
||||
* update exponent. */
|
||||
Ext_leftshiftby1(extent);
|
||||
|
||||
/* Discover first one bit to determine shift amount. Use a
|
||||
* modified binary search. We have already shifted the result
|
||||
* one position right and still not found a one so the remainder
|
||||
* of the extension must be zero and simplifies rounding. */
|
||||
/* Scan bytes */
|
||||
while(Sgl_iszero_hiddenhigh7mantissa(result))
|
||||
{
|
||||
Sgl_leftshiftby8(result);
|
||||
if((result_exponent -= 8) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Now narrow it down to the nibble */
|
||||
if(Sgl_iszero_hiddenhigh3mantissa(result))
|
||||
{
|
||||
/* The lower nibble contains the normalizing one */
|
||||
Sgl_leftshiftby4(result);
|
||||
if((result_exponent -= 4) <= 0 && !underflowtrap)
|
||||
goto underflow;
|
||||
}
|
||||
/* Select case were first bit is set (already normalized)
|
||||
* otherwise select the proper shift. */
|
||||
if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
|
||||
{
|
||||
/* Already normalized */
|
||||
if(result_exponent <= 0) goto underflow;
|
||||
Sgl_set_sign(result,/*using*/sign_save);
|
||||
Sgl_set_exponent(result,/*using*/result_exponent);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
Sgl_sethigh4bits(result,/*using*/sign_save);
|
||||
switch(jumpsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Sgl_leftshiftby3(result);
|
||||
result_exponent -= 3;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
Sgl_leftshiftby2(result);
|
||||
result_exponent -= 2;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
Sgl_leftshiftby1(result);
|
||||
result_exponent -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result_exponent > 0)
|
||||
{
|
||||
Sgl_set_exponent(result,/*using*/result_exponent);
|
||||
*dstptr = result; /* Sign bit is already set */
|
||||
return(NOEXCEPTION);
|
||||
}
|
||||
/* Fixup potential underflows */
|
||||
underflow:
|
||||
if(Is_underflowtrap_enabled())
|
||||
{
|
||||
Sgl_set_sign(result,sign_save);
|
||||
Sgl_setwrapped_exponent(result,result_exponent,unfl);
|
||||
*dstptr = result;
|
||||
/* inexact = FALSE */
|
||||
return(UNDERFLOWEXCEPTION);
|
||||
}
|
||||
/*
|
||||
* Since we cannot get an inexact denormalized result,
|
||||
* we can now return.
|
||||
*/
|
||||
Sgl_right_align(result,/*by*/(1-result_exponent),extent);
|
||||
Sgl_clear_signexponent(result);
|
||||
Sgl_set_sign(result,sign_save);
|
||||
*dstptr = result;
|
||||
return(NOEXCEPTION);
|
||||
} /* end if(hidden...)... */
|
||||
/* Fall through and round */
|
||||
} /* end if(save >= 0)... */
|
||||
else
|
||||
{
|
||||
/* Add magnitudes */
|
||||
Sgl_addition(left,right,/*to*/result);
|
||||
if(Sgl_isone_hiddenoverflow(result))
|
||||
{
|
||||
/* Prenormalization required. */
|
||||
Sgl_rightshiftby1_withextent(result,extent,extent);
|
||||
Sgl_arithrightshiftby1(result);
|
||||
result_exponent++;
|
||||
} /* end if hiddenoverflow... */
|
||||
} /* end else ...sub magnitudes... */
|
||||
|
||||
/* Round the result. If the extension is all zeros,then the result is
|
||||
* exact. Otherwise round in the correct direction. No underflow is
|
||||
* possible. If a postnormalization is necessary, then the mantissa is
|
||||
* all zeros so no shift is needed. */
|
||||
round:
|
||||
if(Ext_isnotzero(extent))
|
||||
{
|
||||
inexact = TRUE;
|
||||
switch(Rounding_mode())
|
||||
{
|
||||
case ROUNDNEAREST: /* The default. */
|
||||
if(Ext_isone_sign(extent))
|
||||
{
|
||||
/* at least 1/2 ulp */
|
||||
if(Ext_isnotzero_lower(extent) ||
|
||||
Sgl_isone_lowmantissa(result))
|
||||
{
|
||||
/* either exactly half way and odd or more than 1/2ulp */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDPLUS:
|
||||
if(Sgl_iszero_sign(result))
|
||||
{
|
||||
/* Round up positive results */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
break;
|
||||
|
||||
case ROUNDMINUS:
|
||||
if(Sgl_isone_sign(result))
|
||||
{
|
||||
/* Round down negative results */
|
||||
Sgl_increment(result);
|
||||
}
|
||||
|
||||
case ROUNDZERO:;
|
||||
/* truncate is simple */
|
||||
} /* end switch... */
|
||||
if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
|
||||
}
|
||||
if(result_exponent == SGL_INFINITY_EXPONENT)
|
||||
{
|
||||
/* Overflow */
|
||||
if(Is_overflowtrap_enabled())
|
||||
{
|
||||
Sgl_setwrapped_exponent(result,result_exponent,ovfl);
|
||||
*dstptr = result;
|
||||
if (inexact)
|
||||
if (Is_inexacttrap_enabled())
|
||||
return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(OVERFLOWEXCEPTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
Set_overflowflag();
|
||||
inexact = TRUE;
|
||||
Sgl_setoverflow(result);
|
||||
}
|
||||
}
|
||||
else Sgl_set_exponent(result,result_exponent);
|
||||
*dstptr = result;
|
||||
if(inexact)
|
||||
if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
|
||||
else Set_inexactflag();
|
||||
return(NOEXCEPTION);
|
||||
}
|
486
arch/parisc/math-emu/sgl_float.h
Обычный файл
486
arch/parisc/math-emu/sgl_float.h
Обычный файл
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
|
||||
*
|
||||
* Floating-point emulation code
|
||||
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __NO_PA_HDRS
|
||||
PA header file -- do not include this header file for non-PA builds.
|
||||
#endif
|
||||
|
||||
/* 32-bit word grabing functions */
|
||||
#define Sgl_firstword(value) Sall(value)
|
||||
#define Sgl_secondword(value) dummy_location
|
||||
#define Sgl_thirdword(value) dummy_location
|
||||
#define Sgl_fourthword(value) dummy_location
|
||||
|
||||
#define Sgl_sign(object) Ssign(object)
|
||||
#define Sgl_exponent(object) Sexponent(object)
|
||||
#define Sgl_signexponent(object) Ssignexponent(object)
|
||||
#define Sgl_mantissa(object) Smantissa(object)
|
||||
#define Sgl_exponentmantissa(object) Sexponentmantissa(object)
|
||||
#define Sgl_all(object) Sall(object)
|
||||
|
||||
/* sgl_and_signs ands the sign bits of each argument and puts the result
|
||||
* into the first argument. sgl_or_signs ors those same sign bits */
|
||||
#define Sgl_and_signs( src1dst, src2) \
|
||||
Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
|
||||
#define Sgl_or_signs( src1dst, src2) \
|
||||
Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst)
|
||||
|
||||
/* The hidden bit is always the low bit of the exponent */
|
||||
#define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1)
|
||||
#define Sgl_clear_signexponent_set_hidden(srcdst) \
|
||||
Deposit_ssignexponent(srcdst,1)
|
||||
#define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31)
|
||||
#define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff
|
||||
|
||||
/* varamount must be less than 32 for the next three functions */
|
||||
#define Sgl_rightshift(srcdst, varamount) \
|
||||
Sall(srcdst) >>= varamount
|
||||
#define Sgl_leftshift(srcdst, varamount) \
|
||||
Sall(srcdst) <<= varamount
|
||||
#define Sgl_rightshift_exponentmantissa(srcdst, varamount) \
|
||||
Sall(srcdst) = \
|
||||
(Sexponentmantissa(srcdst) >> varamount) | \
|
||||
(Sall(srcdst) & ((unsigned int)1<<31))
|
||||
|
||||
#define Sgl_leftshiftby1_withextent(left,right,result) \
|
||||
Shiftdouble(Sall(left),Extall(right),31,Sall(result))
|
||||
|
||||
#define Sgl_rightshiftby1_withextent(left,right,dst) \
|
||||
Shiftdouble(Sall(left),Extall(right),1,Extall(right))
|
||||
#define Sgl_arithrightshiftby1(srcdst) \
|
||||
Sall(srcdst) = (int)Sall(srcdst) >> 1
|
||||
|
||||
/* Sign extend the sign bit with an integer destination */
|
||||
#define Sgl_signextendedsign(value) Ssignedsign(value)
|
||||
|
||||
#define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value))
|
||||
#define Sgl_increment(sgl_value) Sall(sgl_value) += 1
|
||||
#define Sgl_increment_mantissa(sgl_value) \
|
||||
Deposit_smantissa(sgl_value,sgl_value+1)
|
||||
#define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1
|
||||
|
||||
#define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0)
|
||||
#define Sgl_isone_hiddenoverflow(sgl_value) \
|
||||
(Is_shiddenoverflow(sgl_value)!=0)
|
||||
#define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0)
|
||||
#define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0)
|
||||
#define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff)
|
||||
#define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0)
|
||||
#define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \
|
||||
(Shiddenhigh7mantissa(sgl_value)!=0)
|
||||
#define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0)
|
||||
#define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0)
|
||||
#define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0)
|
||||
#define Sgl_isnotzero_exponentmantissa(sgl_value) \
|
||||
(Sexponentmantissa(sgl_value)!=0)
|
||||
#define Sgl_iszero(sgl_value) (Sall(sgl_value)==0)
|
||||
#define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0)
|
||||
#define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0)
|
||||
#define Sgl_iszero_hiddenoverflow(sgl_value) \
|
||||
(Is_shiddenoverflow(sgl_value)==0)
|
||||
#define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \
|
||||
(Shiddenhigh3mantissa(sgl_value)==0)
|
||||
#define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \
|
||||
(Shiddenhigh7mantissa(sgl_value)==0)
|
||||
#define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0)
|
||||
#define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0)
|
||||
#define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0)
|
||||
#define Sgl_iszero_exponentmantissa(sgl_value) \
|
||||
(Sexponentmantissa(sgl_value)==0)
|
||||
#define Sgl_isinfinity_exponent(sgl_value) \
|
||||
(Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT)
|
||||
#define Sgl_isnotinfinity_exponent(sgl_value) \
|
||||
(Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT)
|
||||
#define Sgl_isinfinity(sgl_value) \
|
||||
(Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
|
||||
Sgl_mantissa(sgl_value)==0)
|
||||
#define Sgl_isnan(sgl_value) \
|
||||
(Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \
|
||||
Sgl_mantissa(sgl_value)!=0)
|
||||
#define Sgl_isnotnan(sgl_value) \
|
||||
(Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \
|
||||
Sgl_mantissa(sgl_value)==0)
|
||||
#define Sgl_islessthan(sgl_op1,sgl_op2) \
|
||||
(Sall(sgl_op1) < Sall(sgl_op2))
|
||||
#define Sgl_isgreaterthan(sgl_op1,sgl_op2) \
|
||||
(Sall(sgl_op1) > Sall(sgl_op2))
|
||||
#define Sgl_isnotlessthan(sgl_op1,sgl_op2) \
|
||||
(Sall(sgl_op1) >= Sall(sgl_op2))
|
||||
#define Sgl_isequal(sgl_op1,sgl_op2) \
|
||||
(Sall(sgl_op1) == Sall(sgl_op2))
|
||||
|
||||
#define Sgl_leftshiftby8(sgl_value) \
|
||||
Sall(sgl_value) <<= 8
|
||||
#define Sgl_leftshiftby4(sgl_value) \
|
||||
Sall(sgl_value) <<= 4
|
||||
#define Sgl_leftshiftby3(sgl_value) \
|
||||
Sall(sgl_value) <<= 3
|
||||
#define Sgl_leftshiftby2(sgl_value) \
|
||||
Sall(sgl_value) <<= 2
|
||||
#define Sgl_leftshiftby1(sgl_value) \
|
||||
Sall(sgl_value) <<= 1
|
||||
#define Sgl_rightshiftby1(sgl_value) \
|
||||
Sall(sgl_value) >>= 1
|
||||
#define Sgl_rightshiftby4(sgl_value) \
|
||||
Sall(sgl_value) >>= 4
|
||||
#define Sgl_rightshiftby8(sgl_value) \
|
||||
Sall(sgl_value) >>= 8
|
||||
|
||||
#define Sgl_ismagnitudeless(signlessleft,signlessright) \
|
||||
/* unsigned int signlessleft, signlessright; */ \
|
||||
(signlessleft < signlessright)
|
||||
|
||||
|
||||
#define Sgl_copytoint_exponentmantissa(source,dest) \
|
||||
dest = Sexponentmantissa(source)
|
||||
|
||||
/* A quiet NaN has the high mantissa bit clear and at least on other (in this
|
||||
* case the adjacent bit) bit set. */
|
||||
#define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1)
|
||||
#define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp)
|
||||
|
||||
#define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value)
|
||||
#define Sgl_set_exponentmantissa(dest,value) \
|
||||
Deposit_sexponentmantissa(dest,value)
|
||||
|
||||
/* An infinity is represented with the max exponent and a zero mantissa */
|
||||
#define Sgl_setinfinity_exponent(sgl_value) \
|
||||
Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT)
|
||||
#define Sgl_setinfinity_exponentmantissa(sgl_value) \
|
||||
Deposit_sexponentmantissa(sgl_value, \
|
||||
(SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))))
|
||||
#define Sgl_setinfinitypositive(sgl_value) \
|
||||
Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))
|
||||
#define Sgl_setinfinitynegative(sgl_value) \
|
||||
Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \
|
||||
| ((unsigned int)1<<31)
|
||||
#define Sgl_setinfinity(sgl_value,sign) \
|
||||
Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \
|
||||
((unsigned int)sign << 31)
|
||||
#define Sgl_sethigh4bits(sgl_value, extsign) \
|
||||
Deposit_shigh4(sgl_value,extsign)
|
||||
#define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign)
|
||||
#define Sgl_invert_sign(sgl_value) \
|
||||
Deposit_ssign(sgl_value,~Ssign(sgl_value))
|
||||
#define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1)
|
||||
#define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1)
|
||||
#define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff
|
||||
#define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff
|
||||
#define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000
|
||||
#define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000
|
||||
#define Sgl_setzero(sgl_value) Sall(sgl_value) = 0
|
||||
#define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31
|
||||
|
||||
/* Use following macro for both overflow & underflow conditions */
|
||||
#define ovfl -
|
||||
#define unfl +
|
||||
#define Sgl_setwrapped_exponent(sgl_value,exponent,op) \
|
||||
Deposit_sexponent(sgl_value,(exponent op SGL_WRAP))
|
||||
|
||||
#define Sgl_setlargestpositive(sgl_value) \
|
||||
Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
|
||||
| ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 )
|
||||
#define Sgl_setlargestnegative(sgl_value) \
|
||||
Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
|
||||
| ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \
|
||||
| ((unsigned int)1<<31)
|
||||
|
||||
#define Sgl_setnegativeinfinity(sgl_value) \
|
||||
Sall(sgl_value) = \
|
||||
((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH))
|
||||
#define Sgl_setlargest(sgl_value,sign) \
|
||||
Sall(sgl_value) = (unsigned int)sign << 31 | \
|
||||
(((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
|
||||
| ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
|
||||
#define Sgl_setlargest_exponentmantissa(sgl_value) \
|
||||
Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) | \
|
||||
(((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \
|
||||
| ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
|
||||
|
||||
/* The high bit is always zero so arithmetic or logical shifts will work. */
|
||||
#define Sgl_right_align(srcdst,shift,extent) \
|
||||
/* sgl_floating_point srcdst; int shift; extension extent */ \
|
||||
if (shift < 32) { \
|
||||
Extall(extent) = Sall(srcdst) << (32-(shift)); \
|
||||
Sall(srcdst) >>= shift; \
|
||||
} \
|
||||
else { \
|
||||
Extall(extent) = Sall(srcdst); \
|
||||
Sall(srcdst) = 0; \
|
||||
}
|
||||
#define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value)
|
||||
#define Sgl_hidden(sgl_value) Shidden(sgl_value)
|
||||
#define Sgl_lowmantissa(sgl_value) Slow(sgl_value)
|
||||
|
||||
/* The left argument is never smaller than the right argument */
|
||||
#define Sgl_subtract(sgl_left,sgl_right,sgl_result) \
|
||||
Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right)
|
||||
|
||||
/* Subtract right augmented with extension from left augmented with zeros and
|
||||
* store into result and extension. */
|
||||
#define Sgl_subtract_withextension(left,right,extent,result) \
|
||||
/* sgl_floating_point left,right,result; extension extent */ \
|
||||
Sgl_subtract(left,right,result); \
|
||||
if((Extall(extent) = 0-Extall(extent))) \
|
||||
Sall(result) = Sall(result)-1
|
||||
|
||||
#define Sgl_addition(sgl_left,sgl_right,sgl_result) \
|
||||
Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right)
|
||||
|
||||
#define Sgl_xortointp1(left,right,result) \
|
||||
result = Sall(left) XOR Sall(right);
|
||||
|
||||
#define Sgl_xorfromintp1(left,right,result) \
|
||||
Sall(result) = left XOR Sall(right)
|
||||
|
||||
/* Need to Initialize */
|
||||
#define Sgl_makequietnan(dest) \
|
||||
Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
|
||||
| (1<<(32-(1+SGL_EXP_LENGTH+2)))
|
||||
#define Sgl_makesignalingnan(dest) \
|
||||
Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \
|
||||
| (1<<(32-(1+SGL_EXP_LENGTH+1)))
|
||||
|
||||
#define Sgl_normalize(sgl_opnd,exponent) \
|
||||
while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \
|
||||
Sgl_leftshiftby8(sgl_opnd); \
|
||||
exponent -= 8; \
|
||||
} \
|
||||
if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \
|
||||
Sgl_leftshiftby4(sgl_opnd); \
|
||||
exponent -= 4; \
|
||||
} \
|
||||
while(Sgl_iszero_hidden(sgl_opnd)) { \
|
||||
Sgl_leftshiftby1(sgl_opnd); \
|
||||
exponent -= 1; \
|
||||
}
|
||||
|
||||
#define Sgl_setoverflow(sgl_opnd) \
|
||||
/* set result to infinity or largest number */ \
|
||||
switch (Rounding_mode()) { \
|
||||
case ROUNDPLUS: \
|
||||
if (Sgl_isone_sign(sgl_opnd)) { \
|
||||
Sgl_setlargestnegative(sgl_opnd); \
|
||||
} \
|
||||
else { \
|
||||
Sgl_setinfinitypositive(sgl_opnd); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDMINUS: \
|
||||
if (Sgl_iszero_sign(sgl_opnd)) { \
|
||||
Sgl_setlargestpositive(sgl_opnd); \
|
||||
} \
|
||||
else { \
|
||||
Sgl_setinfinitynegative(sgl_opnd); \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDNEAREST: \
|
||||
Sgl_setinfinity_exponentmantissa(sgl_opnd); \
|
||||
break; \
|
||||
case ROUNDZERO: \
|
||||
Sgl_setlargest_exponentmantissa(sgl_opnd); \
|
||||
}
|
||||
|
||||
#define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \
|
||||
Sgl_clear_signexponent_set_hidden(opnd); \
|
||||
if (exponent >= (1 - SGL_P)) { \
|
||||
guard = (Sall(opnd) >> -exponent) & 1; \
|
||||
if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \
|
||||
inexact = guard | sticky; \
|
||||
Sall(opnd) >>= (1-exponent); \
|
||||
} \
|
||||
else { \
|
||||
guard = 0; \
|
||||
sticky |= Sall(opnd); \
|
||||
inexact = sticky; \
|
||||
Sgl_setzero(opnd); \
|
||||
}
|
||||
|
||||
/*
|
||||
* The fused multiply add instructions requires a single extended format,
|
||||
* with 48 bits of mantissa.
|
||||
*/
|
||||
#define SGLEXT_THRESHOLD 48
|
||||
|
||||
#define Sglext_setzero(valA,valB) \
|
||||
Sextallp1(valA) = 0; Sextallp2(valB) = 0
|
||||
|
||||
#define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0)
|
||||
#define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0)
|
||||
#define Sglext_isone_highp2(val) (Sexthighp2(val)!=0)
|
||||
#define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0)
|
||||
#define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0)
|
||||
|
||||
#define Sgl_copytoptr(src,destptr) *destptr = src
|
||||
#define Sgl_copyfromptr(srcptr,dest) dest = *srcptr
|
||||
#define Sglext_copy(srca,srcb,desta,destb) \
|
||||
Sextallp1(desta) = Sextallp1(srca); \
|
||||
Sextallp2(destb) = Sextallp2(srcb)
|
||||
#define Sgl_copyto_sglext(src1,dest1,dest2) \
|
||||
Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0
|
||||
|
||||
#define Sglext_swap_lower(leftp2,rightp2) \
|
||||
Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
|
||||
Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \
|
||||
Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2)
|
||||
|
||||
#define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1)
|
||||
|
||||
/* The high bit is always zero so arithmetic or logical shifts will work. */
|
||||
#define Sglext_right_align(srcdstA,srcdstB,shift) \
|
||||
{int shiftamt, sticky; \
|
||||
shiftamt = shift % 32; \
|
||||
sticky = 0; \
|
||||
switch (shift/32) { \
|
||||
case 0: if (shiftamt > 0) { \
|
||||
sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \
|
||||
Variable_shift_double(Sextallp1(srcdstA), \
|
||||
Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \
|
||||
Sextallp1(srcdstA) >>= shiftamt; \
|
||||
} \
|
||||
break; \
|
||||
case 1: if (shiftamt > 0) { \
|
||||
sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \
|
||||
Sextallp2(srcdstB); \
|
||||
} \
|
||||
else { \
|
||||
sticky = Sextallp2(srcdstB); \
|
||||
} \
|
||||
Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \
|
||||
Sextallp1(srcdstA) = 0; \
|
||||
break; \
|
||||
} \
|
||||
if (sticky) Sglext_setone_lowmantissap2(srcdstB); \
|
||||
}
|
||||
|
||||
/* The left argument is never smaller than the right argument */
|
||||
#define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
|
||||
if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \
|
||||
Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \
|
||||
Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta)
|
||||
|
||||
#define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \
|
||||
/* If the sum of the low words is less than either source, then \
|
||||
* an overflow into the next word occurred. */ \
|
||||
if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \
|
||||
Sextallp2(rightb)) \
|
||||
Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \
|
||||
else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)
|
||||
|
||||
|
||||
#define Sglext_arithrightshiftby1(srcdstA,srcdstB) \
|
||||
Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \
|
||||
Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1
|
||||
|
||||
#define Sglext_leftshiftby8(valA,valB) \
|
||||
Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \
|
||||
Sextallp2(valB) <<= 8
|
||||
#define Sglext_leftshiftby4(valA,valB) \
|
||||
Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \
|
||||
Sextallp2(valB) <<= 4
|
||||
#define Sglext_leftshiftby3(valA,valB) \
|
||||
Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \
|
||||
Sextallp2(valB) <<= 3
|
||||
#define Sglext_leftshiftby2(valA,valB) \
|
||||
Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \
|
||||
Sextallp2(valB) <<= 2
|
||||
#define Sglext_leftshiftby1(valA,valB) \
|
||||
Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \
|
||||
Sextallp2(valB) <<= 1
|
||||
|
||||
#define Sglext_rightshiftby4(valueA,valueB) \
|
||||
Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \
|
||||
Sextallp1(valueA) >>= 4
|
||||
#define Sglext_rightshiftby3(valueA,valueB) \
|
||||
Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \
|
||||
Sextallp1(valueA) >>= 3
|
||||
#define Sglext_rightshiftby1(valueA,valueB) \
|
||||
Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \
|
||||
Sextallp1(valueA) >>= 1
|
||||
|
||||
#define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result)
|
||||
#define Sglext_xorfromintp1(left,right,result) \
|
||||
Sgl_xorfromintp1(left,right,result)
|
||||
#define Sglext_copytoint_exponentmantissa(src,dest) \
|
||||
Sgl_copytoint_exponentmantissa(src,dest)
|
||||
#define Sglext_ismagnitudeless(signlessleft,signlessright) \
|
||||
Sgl_ismagnitudeless(signlessleft,signlessright)
|
||||
|
||||
#define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign)
|
||||
#define Sglext_clear_signexponent_set_hidden(srcdst) \
|
||||
Sgl_clear_signexponent_set_hidden(srcdst)
|
||||
#define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst)
|
||||
#define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst)
|
||||
#define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value)
|
||||
|
||||
#define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \
|
||||
{int sticky; \
|
||||
is_tiny = TRUE; \
|
||||
if (exponent == 0 && Sextallp2(opndp2)) { \
|
||||
switch (Rounding_mode()) { \
|
||||
case ROUNDPLUS: \
|
||||
if (Sgl_iszero_sign(opndp1)) \
|
||||
if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
|
||||
is_tiny = FALSE; \
|
||||
break; \
|
||||
case ROUNDMINUS: \
|
||||
if (Sgl_isone_sign(opndp1)) { \
|
||||
if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
|
||||
is_tiny = FALSE; \
|
||||
} \
|
||||
break; \
|
||||
case ROUNDNEAREST: \
|
||||
if (Sglext_isone_highp2(opndp2) && \
|
||||
(Sglext_isone_lowp1(opndp1) || \
|
||||
Sglext_isnotzero_low31p2(opndp2))) \
|
||||
if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \
|
||||
is_tiny = FALSE; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
Sglext_clear_signexponent_set_hidden(opndp1); \
|
||||
if (exponent >= (1-DBL_P)) { \
|
||||
if (exponent >= -31) { \
|
||||
if (exponent > -31) { \
|
||||
sticky = Sextallp2(opndp2) << 31+exponent; \
|
||||
Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \
|
||||
Sextallp1(opndp1) >>= 1-exponent; \
|
||||
} \
|
||||
else { \
|
||||
sticky = Sextallp2(opndp2); \
|
||||
Sextallp2(opndp2) = Sextallp1(opndp1); \
|
||||
Sextallp1(opndp1) = 0; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
sticky = (Sextallp1(opndp1) << 31+exponent) | \
|
||||
Sextallp2(opndp2); \
|
||||
Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \
|
||||
Sextallp1(opndp1) = 0; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \
|
||||
Sglext_setzero(opndp1,opndp2); \
|
||||
} \
|
||||
if (sticky) Sglext_setone_lowmantissap2(opndp2); \
|
||||
exponent = 0; \
|
||||
}
|
Ссылка в новой задаче
Block a user