diff options
Diffstat (limited to 'sys/arch')
43 files changed, 10749 insertions, 0 deletions
diff --git a/sys/arch/hppa/spmath/cnv_float.h b/sys/arch/hppa/spmath/cnv_float.h new file mode 100644 index 00000000000..adf7b6bc5e6 --- /dev/null +++ b/sys/arch/hppa/spmath/cnv_float.h @@ -0,0 +1,419 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)cnv_float.h: $Revision: 1.1 $ $Date: 1998/06/23 20:33:50 $ + * $Locker: $ + * + */ + +/* + * 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 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) = 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; \ + } + +/* + * The following 4 functions handle the assignment of a floating point + * number to a 32-bit integer in cases where the floating point number + * is too large (or small) to fit in the integer field. + * + * In all these cases, HP-UX would return an UNIMPLEMENTEDEXCEPTION + * resulting in a SIGFPE being sent to the process. For BSD's math + * library (and various other applications), this was unacceptable. + * As a result, we now return maxint/minint (like most other OS's) + * and either return an INEXACTEXCEPTION (SIGFPE) or set the inexact + * flag (so that the program may continue execution). + * + * After discussing this with Jerry Huck @ HP, the one case where we + * differ from BSD is for programs that try to convert a NaN to an + * integer; in this case, we will return an UNIMPLEMENTEDEXCEPTION + * since doing anything else would be completely unreasonable. + * + * jef + */ + +#define Dbl_return_overflow(srcp1, srcp2, resultp) \ + { \ + if (Dbl_isnan(srcp1, srcp2)) \ + return(UNIMPLEMENTEDEXCEPTION); \ + if (Dbl_iszero_sign(srcp1)) \ + *resultp = 0x7fffffff; \ + else \ + *resultp = 0x80000000; \ + if (Is_overflowtrap_enabled()) { \ + if (Is_inexacttrap_enabled()) \ + return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); \ + else \ + Set_inexactflag(); \ + return(OVERFLOWEXCEPTION); \ + } \ + return(NOEXCEPTION); \ + } + +#define Dbl_return_overflow_dbl(srcp1, srcp2, resultp) \ + { \ + if (Dbl_isnan(srcp1, srcp2)) \ + return(UNIMPLEMENTEDEXCEPTION); \ + if (Dbl_iszero_sign(srcp1)) { \ + Dint_copytoptr(0x7fffffff,0xffffffff,resultp); \ + } else { \ + Dint_copytoptr(0x80000000,0x00000000,resultp); \ + } \ + if (Is_overflowtrap_enabled()) { \ + if (Is_inexacttrap_enabled()) \ + return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); \ + else \ + Set_inexactflag(); \ + return(OVERFLOWEXCEPTION); \ + } \ + return(NOEXCEPTION); \ + } + +#define Sgl_return_overflow(src, resultp) \ + { \ + if (Sgl_isnan(src)) \ + return(UNIMPLEMENTEDEXCEPTION); \ + if (Sgl_iszero_sign(src)) \ + *resultp = 0x7fffffff; \ + else \ + *resultp = 0x80000000; \ + if (Is_overflowtrap_enabled()) { \ + if (Is_inexacttrap_enabled()) \ + return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); \ + else \ + Set_inexactflag(); \ + return(OVERFLOWEXCEPTION); \ + } \ + return(NOEXCEPTION); \ + } + +#define Sgl_return_overflow_dbl(src, resultp) \ + { \ + if (Sgl_isnan(src)) \ + return(UNIMPLEMENTEDEXCEPTION); \ + if (Sgl_iszero_sign(src)) { \ + Dint_copytoptr(0x7fffffff,0xffffffff,resultp); \ + } else { \ + Dint_copytoptr(0x80000000,0x00000000,resultp); \ + } \ + if (Is_overflowtrap_enabled()) { \ + if (Is_inexacttrap_enabled()) \ + return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); \ + else \ + Set_inexactflag(); \ + return(OVERFLOWEXCEPTION); \ + } \ + return(NOEXCEPTION); \ + } + diff --git a/sys/arch/hppa/spmath/dbl_float.h b/sys/arch/hppa/spmath/dbl_float.h new file mode 100644 index 00000000000..0ad4531a02e --- /dev/null +++ b/sys/arch/hppa/spmath/dbl_float.h @@ -0,0 +1,552 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)dbl_float.h: $Revision: 1.1 $ $Date: 1998/06/23 20:33:51 $ + * $Locker: $ + * + */ +/************************************** + * Declare double precision functions * + **************************************/ + +/* 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)|~(1<<31)) & Dallp1(src1dst) +#define Dbl_or_signs( src1dst, src2) \ + Dallp1(src1dst) = (Dallp1(src2)&(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) &= ~(1<<31) +#define Dbl_clear_signexponent(srcdst) \ + Dallp1(srcdst) &= Dmantissap1((unsigned)-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) &= (1<<31); /* clear exponentmantissa 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)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) = (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) = (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) = 1 << 31; Dallp2(dbl_value) = 0 +#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = 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 ) | (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) = (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; \ + } diff --git a/sys/arch/hppa/spmath/dfadd.c b/sys/arch/hppa/spmath/dfadd.c new file mode 100644 index 00000000000..a6a28f88457 --- /dev/null +++ b/sys/arch/hppa/spmath/dfadd.c @@ -0,0 +1,524 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfadd.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:51 $ + */ + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double_add: add two double precision values. + */ +dbl_fadd(leftptr, rightptr, dstptr, status) + dbl_floating_point *leftptr, *rightptr, *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); + } diff --git a/sys/arch/hppa/spmath/dfcmp.c b/sys/arch/hppa/spmath/dfcmp.c new file mode 100644 index 00000000000..070010eba01 --- /dev/null +++ b/sys/arch/hppa/spmath/dfcmp.c @@ -0,0 +1,181 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfcmp.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:52 $ + */ + + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * dbl_cmp: compare two values + */ +dbl_fcmp(leftptr, rightptr, cond, status) + dbl_floating_point *leftptr, *rightptr; + unsigned int cond; /* The predicate to be tested */ + unsigned int *status; + { + 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); + } diff --git a/sys/arch/hppa/spmath/dfdiv.c b/sys/arch/hppa/spmath/dfdiv.c new file mode 100644 index 00000000000..8f331698431 --- /dev/null +++ b/sys/arch/hppa/spmath/dfdiv.c @@ -0,0 +1,404 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfdiv.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:52 $ + */ + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double Precision Floating-point Divide + */ + +dbl_fdiv(srcptr1,srcptr2,dstptr,status) + +dbl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/dfmpy.c b/sys/arch/hppa/spmath/dfmpy.c new file mode 100644 index 00000000000..77e56a024b6 --- /dev/null +++ b/sys/arch/hppa/spmath/dfmpy.c @@ -0,0 +1,395 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfmpy.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:53 $ + */ + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double Precision Floating-point Multiply + */ + +dbl_fmpy(srcptr1,srcptr2,dstptr,status) + +dbl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/dfrem.c b/sys/arch/hppa/spmath/dfrem.c new file mode 100644 index 00000000000..61be22d148a --- /dev/null +++ b/sys/arch/hppa/spmath/dfrem.c @@ -0,0 +1,301 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfrem.c,v $ + * $Revision: 1.1 $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:53 $ + */ + + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double Precision Floating-point Remainder + */ + +dbl_frem(srcptr1,srcptr2,dstptr,status) + +dbl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/dfsqrt.c b/sys/arch/hppa/spmath/dfsqrt.c new file mode 100644 index 00000000000..918e1024ec0 --- /dev/null +++ b/sys/arch/hppa/spmath/dfsqrt.c @@ -0,0 +1,196 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfsqrt.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:54 $ + */ + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double Floating-point Square Root + */ + +/*ARGSUSED*/ +dbl_fsqrt(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr, *dstptr; +unsigned int *nullptr, *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); +} diff --git a/sys/arch/hppa/spmath/dfsub.c b/sys/arch/hppa/spmath/dfsub.c new file mode 100644 index 00000000000..03196050726 --- /dev/null +++ b/sys/arch/hppa/spmath/dfsub.c @@ -0,0 +1,526 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/dfsub.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:54 $ + */ + +#include "../spmath/float.h" +#include "../spmath/dbl_float.h" + +/* + * Double_subtract: subtract two double precision values. + */ +dbl_fsub(leftptr, rightptr, dstptr, status) + dbl_floating_point *leftptr, *rightptr, *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); + } diff --git a/sys/arch/hppa/spmath/divsfm.c b/sys/arch/hppa/spmath/divsfm.c new file mode 100644 index 00000000000..e088cc36064 --- /dev/null +++ b/sys/arch/hppa/spmath/divsfm.c @@ -0,0 +1,110 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divsfm.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:55 $ + */ + + +#include "../spmath/md.h" + +VOID divsfm(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + register int sign, op1_sign; + + /* check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + + /* get sign of result */ + sign = opnd1 ^ opnd2; + + /* get absolute value of operands */ + if (opnd1 < 0) { + opnd1 = -opnd1; + op1_sign = TRUE; + } + else op1_sign = FALSE; + if (opnd2 < 0) opnd2 = -opnd2; + + /* + * check for overflow + * + * if abs(opnd1) < 0, then opnd1 = -2**31 + * and abs(opnd1) >= abs(opnd2) always + */ + if (opnd1 >= opnd2 || opnd1 < 0) { + /* check for opnd2 = -2**31 */ + if (opnd2 < 0 && opnd1 != opnd2) { + result_hi = 0; /* remainder = 0 */ + result_lo = opnd1 << 1; + } + else { + overflow = TRUE; + return; + } + } + else { + /* do the divide */ + divu(opnd1,0,opnd2,result); + + /* return positive residue */ + if (op1_sign && result_hi) { + result_hi = opnd2 - result_hi; + result_lo++; + } + } + + /* check for overflow */ + if (result_lo < 0) { + overflow = TRUE; + return; + } + overflow = FALSE; + + /* return appropriately signed result */ + if (sign<0) result_lo = -result_lo; + return; +} diff --git a/sys/arch/hppa/spmath/divsfr.c b/sys/arch/hppa/spmath/divsfr.c new file mode 100644 index 00000000000..d74ff9456b8 --- /dev/null +++ b/sys/arch/hppa/spmath/divsfr.c @@ -0,0 +1,105 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divsfr.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:55 $ + */ + + +#include "../spmath/md.h" + +VOID divsfr(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + int sign, op1_sign; + + /* check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + + /* get sign of result */ + sign = opnd1 ^ opnd2; + + /* get absolute value of operands */ + if (opnd1 < 0) { + opnd1 = -opnd1; + op1_sign = TRUE; + } + else op1_sign = FALSE; + if (opnd2 < 0) opnd2 = -opnd2; + + /* + * check for overflow + * + * if abs(opnd1) < 0, then opnd1 = -2**31 + * and abs(opnd1) >= abs(opnd2) always + */ + if (opnd1 >= opnd2 || opnd1 < 0) { + /* check for opnd2 = -2**31 */ + if (opnd2 < 0 && opnd1 != opnd2) { + result_hi = 0; /* remainder = 0 */ + result_lo = opnd1 << 1; + } + else { + overflow = TRUE; + return; + } + } + else { + /* do the divide */ + divu(opnd1,0,opnd2,result); + } + + /* check for overflow */ + if (result_lo < 0) { + overflow = TRUE; + return; + } + overflow = FALSE; + + /* return appropriately signed remainder and result */ + if (op1_sign) result_hi = -result_hi; + if (sign<0) result_lo = -result_lo; + return; +} diff --git a/sys/arch/hppa/spmath/divsim.c b/sys/arch/hppa/spmath/divsim.c new file mode 100644 index 00000000000..6459d8bb584 --- /dev/null +++ b/sys/arch/hppa/spmath/divsim.c @@ -0,0 +1,112 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divsim.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:55 $ + */ + + +#include "../spmath/md.h" + +VOID divsim(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + int sign, op1_sign; + + /* check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + + /* get sign of result */ + sign = opnd1 ^ opnd2; + + /* get absolute value of operands */ + if (opnd1 < 0) { + opnd1 = -opnd1; + op1_sign = TRUE; + } + else op1_sign = FALSE; + if (opnd2 < 0) opnd2 = -opnd2; + + /* check for opnd2 == -2**31 */ + if (opnd2 < 0) { + if (opnd1 == opnd2) { + result_hi = 0; /* remainder = 0 */ + result_lo = 1; + } + else { + result_hi = opnd1; /* remainder = opnd1 */ + result_lo = 0; + } + } + else { + /* do the divide */ + divu(0,opnd1,opnd2,result); + + /* + * check for overflow + * + * at this point, the only way we can get overflow + * is with opnd1 = -2**31 and opnd2 = -1 + */ + if (sign>0 && result_lo<0) { + overflow = TRUE; + return; + } + } + overflow = FALSE; + + /* return positive residue */ + if (op1_sign && result_hi) { + result_hi = opnd2 - result_hi; + if (++result_lo < 0) { + overflow = TRUE; + return; + } + } + + /* return appropriately signed result */ + if (sign<0) result_lo = -result_lo; + return; +} diff --git a/sys/arch/hppa/spmath/divsir.c b/sys/arch/hppa/spmath/divsir.c new file mode 100644 index 00000000000..d1f7bda1f86 --- /dev/null +++ b/sys/arch/hppa/spmath/divsir.c @@ -0,0 +1,104 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divsir.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:56 $ + */ + + +#include "../spmath/md.h" + +VOID divsir(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + int sign, op1_sign; + + /* check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + + /* get sign of result */ + sign = opnd1 ^ opnd2; + + /* get absolute value of operands */ + if (opnd1 < 0) { + opnd1 = -opnd1; + op1_sign = TRUE; + } + else op1_sign = FALSE; + if (opnd2 < 0) opnd2 = -opnd2; + + /* check for opnd2 = -2**31 */ + if (opnd2 + opnd2 == 0) { + if (opnd1 == opnd2) { + result_hi = 0; /* remainder = 0 */ + result_lo = 1; + } + else { + result_hi = opnd1; /* remainder = opnd1 */ + result_lo = 0; + } + } + else { + /* do the divide */ + divu(0,opnd1,opnd2,result); + + /* + * check for overflow + * + * at this point, the only way we can get overflow + * is with opnd1 = -2**31 and opnd2 = -1 + */ + if (sign>0 && result_lo<0) { + overflow = TRUE; + return; + } + } + overflow = FALSE; + + /* return appropriately signed remainder and result */ + if (op1_sign) result_hi = -result_hi; + if (sign<0) result_lo = -result_lo; + return; +} diff --git a/sys/arch/hppa/spmath/divu.S b/sys/arch/hppa/spmath/divu.S new file mode 100644 index 00000000000..c4b36ee1abd --- /dev/null +++ b/sys/arch/hppa/spmath/divu.S @@ -0,0 +1,181 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divu.S,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:56 $ + */ + +#include <machine/asm.h> + +/************************************************************************** + * Implement an integer divide routine for 32-bit operands and 32-bit quotient + * and remainder with operand values of zero (divisor only) treated specially. + * + ***************************************************************************/ +/* + * General registers + */ +gr0 .equ 0 /* General register zero */ +rem .equ 3 /* remainder and upper part of dividend */ +quo .equ 4 /* quotient and lower part of dividend */ +dvr .equ 5 /* divisor */ +tp .equ 6 /* temp. reg. */ + +/*****************************************************************************/ + .export divu,entry + .space $TEXT$ + .subspa $CODE$ + .align 4 + .proc + .callinfo + +/*****************************************************************************/ +divu stws,ma rem,4(sp) # save registers on stack + stws,ma quo,4(sp) # save registers on stack + stws,ma dvr,4(sp) # save registers on stack + stws,ma tp,4(sp) # save registers on stack + + addi 0,arg2,dvr # get divisor + addi 0,arg1,quo # get lower dividend + addi 0,arg0,rem # get upper dividend + + comib,>,n 0,dvr,hibit # check for dvr >= 2**31 + addi -1,gr0,tp # set V-bit to 1 + ds 0,tp,0 + add quo,quo,quo # shift msb bit into carry + ds rem,dvr,rem # 1st divide step, if carry + # out, msb of quotient = 0 + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 2nd divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 3rd divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 4th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 5th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 6th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 7th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 8th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 9th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 10th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 11th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 12th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 13th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 14th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 15th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 16th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 17th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 18th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 19th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 20th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 21st divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 22nd divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 23rd divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 24th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 25th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 26th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 27th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 28th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 29th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 30th divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 31st divide step + addc quo,quo,quo # shift quo with/into carry + ds rem,dvr,rem # 32nd divide step, + addc quo,quo,quo # shift last quo bit into quo + addb,>=,n rem,0,finish # branch if pos. rem + add,< dvr,0,0 # if dvr > 0, add dvr + add,tr rem,dvr,rem # for correcting rem. + sub rem,dvr,rem # else subtract dvr +# +# end of divide routine +# +finish stws rem,0(arg3) # save remainder in high part + # of result + stws quo,4(arg3) # save quotient in low part + # of result + ldws,mb -4(sp),tp # restore registers + ldws,mb -4(sp),dvr # restore registers + ldws,mb -4(sp),quo # restore registers + bv 0(rp) # return + ldws,mb -4(sp),rem # restore registers +# +hibit ldo 32(0),tp # initialize loop counter + add quo,quo,quo # shift high bit into carry +loop addc rem,rem,rem # shift in high bit of dvdl + addc,<> 0,0,0 # if bit shifted out of dvdu, + # want to do subtract + comb,<<,n rem,dvr,nosub # if upper dividend > dvr, + sub rem,dvr,rem # subtract and + add,tr dvr,dvr,0 # set carry +nosub addi 0,0,0 # otherwise clear carry + addib,> -1,tp,loop # inc. counter# finished? + addc quo,quo,quo # shift bit of result into dvdl + b finish+4 # finish up + stws rem,0(arg3) # save remainder in high part + # of result + + .procend + .end diff --git a/sys/arch/hppa/spmath/divufr.c b/sys/arch/hppa/spmath/divufr.c new file mode 100644 index 00000000000..6f706ef15ca --- /dev/null +++ b/sys/arch/hppa/spmath/divufr.c @@ -0,0 +1,69 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divufr.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:56 $ + */ + + +#include "../spmath/md.h" + +VOID divufr(opnd1,opnd2,result) + +unsigned int opnd1, opnd2; +struct mdsfu_register *result; +{ + /* check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + + /* check for overflow */ + if (opnd1 >= opnd2) { + overflow = TRUE; + return; + } + overflow = FALSE; + + /* do the divide */ + divu(opnd1,0,opnd2,result); + return; +} diff --git a/sys/arch/hppa/spmath/divuir.c b/sys/arch/hppa/spmath/divuir.c new file mode 100644 index 00000000000..1a575564973 --- /dev/null +++ b/sys/arch/hppa/spmath/divuir.c @@ -0,0 +1,63 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/divuir.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:57 $ + */ + + +#include "../spmath/md.h" + +VOID divuir(opnd1,opnd2,result) + +unsigned int opnd1, opnd2; +struct mdsfu_register *result; +{ + /* get source operands, check divisor for zero */ + if (opnd2 == 0) { + overflow = TRUE; + return; + } + overflow = FALSE; + + /* do the divide */ + divu(0,opnd1,opnd2,result); + return; +} diff --git a/sys/arch/hppa/spmath/fcnvff.c b/sys/arch/hppa/spmath/fcnvff.c new file mode 100644 index 00000000000..c71dbda1d83 --- /dev/null +++ b/sys/arch/hppa/spmath/fcnvff.c @@ -0,0 +1,308 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/fcnvff.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:57 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" +#include "../spmath/cnv_float.h" + +/* + * Single Floating-point to Double Floating-point + */ +/*ARGSUSED*/ +sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr; +dbl_floating_point *dstptr; +unsigned int *nullptr, *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*/ +dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr; +sgl_floating_point *dstptr; +unsigned int *nullptr, *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); +} diff --git a/sys/arch/hppa/spmath/fcnvfx.c b/sys/arch/hppa/spmath/fcnvfx.c new file mode 100644 index 00000000000..519e697e95d --- /dev/null +++ b/sys/arch/hppa/spmath/fcnvfx.c @@ -0,0 +1,462 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/fcnvfx.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:58 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" +#include "../spmath/cnv_float.h" + +/* + * Single Floating-point to Single Fixed-point + */ +/*ARGSUSED*/ +sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr, *nullptr, *status; +int *dstptr; +{ + 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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Sgl_return_overflow(src,dstptr); + } + } + /* + * 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*/ +sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr; +dbl_integer *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Sgl_return_overflow_dbl(src,dstptr); + } + 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*/ +dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr; +int *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Dbl_return_overflow(srcp1,srcp2,dstptr); + } + } + /* + * 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)) { + Dbl_return_overflow(srcp1,srcp2,dstptr); + } + } + } + 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*/ +dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr; +dbl_integer *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Dbl_return_overflow_dbl(srcp1,srcp2,dstptr); + } + } + + /* + * 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); +} diff --git a/sys/arch/hppa/spmath/fcnvfxt.c b/sys/arch/hppa/spmath/fcnvfxt.c new file mode 100644 index 00000000000..7fe4311ccfe --- /dev/null +++ b/sys/arch/hppa/spmath/fcnvfxt.c @@ -0,0 +1,294 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/fcnvfxt.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:58 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" +#include "../spmath/cnv_float.h" + +/* + * Convert single floating-point to single fixed-point format + * with truncated result + */ +/*ARGSUSED*/ +sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr; +int *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Sgl_return_overflow(src,dstptr); + } + } + /* + * 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*/ +sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr; +dbl_integer *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Sgl_return_overflow_dbl(src,dstptr); + } + 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*/ +dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr; +int *dstptr; +unsigned int *nullptr, *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)) { + Dbl_return_overflow(srcp1,srcp2,dstptr); + } + } + /* + * 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*/ +dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr; +dbl_integer *dstptr; +unsigned int *nullptr, *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)) { + /* + * Since source is a number which cannot be + * represented in fixed-point format, return + * largest (or smallest) fixed-point number. + */ + Dbl_return_overflow_dbl(srcp1,srcp2,dstptr); + } + } + /* + * 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); +} diff --git a/sys/arch/hppa/spmath/fcnvxf.c b/sys/arch/hppa/spmath/fcnvxf.c new file mode 100644 index 00000000000..c087155fa0f --- /dev/null +++ b/sys/arch/hppa/spmath/fcnvxf.c @@ -0,0 +1,379 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/fcnvxf.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:33:59 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" +#include "../spmath/cnv_float.h" + +/* + * Convert single fixed-point to single floating-point format + */ + +sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) + +int *srcptr; +sgl_floating_point *dstptr; +unsigned int *nullptr, *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 + */ + +sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) + +int *srcptr; +dbl_floating_point *dstptr; +unsigned int *nullptr, *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 + */ + +dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) + +dbl_integer *srcptr; +sgl_floating_point *dstptr; +unsigned int *nullptr, *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 + */ + +dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) + +dbl_integer *srcptr; +dbl_floating_point *dstptr; +unsigned int *nullptr, *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); +} diff --git a/sys/arch/hppa/spmath/float.h b/sys/arch/hppa/spmath/float.h new file mode 100644 index 00000000000..3bbafecc45c --- /dev/null +++ b/sys/arch/hppa/spmath/float.h @@ -0,0 +1,547 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)float.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:00 $ + * $Locker: $ + * + */ +#include "../spmath/fpbits.h" +#include "../spmath/hppa.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) + +/* + * 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 int sgl_floating_point; +typedef struct dblwd dbl_floating_point; +typedef struct dint dbl_integer; + +/* + * 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 + +/* 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) + +#ifdef TIMEX +#define Set_status_cbit(value) \ + Bitfield_deposit(Bitfield_extract(10,10,Fpustatus_register),11,10,Fpustatus_register); \ + Bitfield_deposit(Bitfield_extract(5,1,Fpustatus_register),10,1,Fpustatus_register); \ + Bitfield_deposit(value,5,1,Fpustatus_register) +#else +#define Set_status_cbit(value) Bitfield_deposit(value,5,1,Fpustatus_register) +#endif + +/******************************* + * 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) + +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 + diff --git a/sys/arch/hppa/spmath/fpbits.h b/sys/arch/hppa/spmath/fpbits.h new file mode 100644 index 00000000000..27f9d9e449d --- /dev/null +++ b/sys/arch/hppa/spmath/fpbits.h @@ -0,0 +1,82 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)fpbits.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:00 $ + * $Locker: $ + * + */ + +/* + * 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)) diff --git a/sys/arch/hppa/spmath/frnd.c b/sys/arch/hppa/spmath/frnd.c new file mode 100644 index 00000000000..4f331d00d0c --- /dev/null +++ b/sys/arch/hppa/spmath/frnd.c @@ -0,0 +1,266 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/frnd.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:01 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" +#include "../spmath/quad_float.h" +#include "../spmath/cnv_float.h" + +/* + * Single Floating-point Round to Integer + */ + +/*ARGSUSED*/ +sgl_frnd(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr, *dstptr; +unsigned int *nullptr, *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*/ +dbl_frnd(srcptr,nullptr,dstptr,status) + +dbl_floating_point *srcptr, *dstptr; +unsigned int *nullptr, *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); +} + +/*ARGSUSED*/ +quad_frnd(srcptr,nullptr,dstptr,status) + +quad_floating_point *srcptr, *dstptr; +unsigned int *nullptr, *status; +{ + return(UNIMPLEMENTEDEXCEPTION); +} + diff --git a/sys/arch/hppa/spmath/hppa.h b/sys/arch/hppa/spmath/hppa.h new file mode 100644 index 00000000000..0995e753cdc --- /dev/null +++ b/sys/arch/hppa/spmath/hppa.h @@ -0,0 +1,58 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)hppa.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:01 $ + * $Locker: $ + */ + +/* 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)) diff --git a/sys/arch/hppa/spmath/impys.S b/sys/arch/hppa/spmath/impys.S new file mode 100644 index 00000000000..7f5251337fc --- /dev/null +++ b/sys/arch/hppa/spmath/impys.S @@ -0,0 +1,323 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/impys.S,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:01 $ + */ + +#include <machine/asm.h> + +/**************************************************************************** + * + * Implement an integer multiply routine for 32-bit operands and 64-bit product + * with operand values of zero (multiplicand only) and -2**31 treated specially. + * The algorithm uses the absolute value of the multiplier, four bits at a time, + * from right to left, to generate partial product. Execution speed is more + * important than program size in this implementation. + * + ***************************************************************************/ +# +# Definitions - General registers +# +gr0 .equ 0 # General register zero +pu .equ 3 # upper part of product +pl .equ 4 # lower part of product +op2 .equ 4 # multiplier +op1 .equ 5 # multiplicand +cnt .equ 6 # count in multiply +brindex .equ 7 # index into the br. table +sign .equ 8 # sign of product +pc .equ 9 # carry bit of product, = 00...01 +pm .equ 10 # value of -1 used in shifting + +#***************************************************************************** + .export impys,entry + .space $TEXT$ + .subspa $CODE$ + .align 4 + .proc + .callinfo +# +#**************************************************************************** +impys stws,ma pu,4(sp) # save registers on stack + stws,ma pl,4(sp) # save registers on stack + stws,ma op1,4(sp) # save registers on stack + stws,ma cnt,4(sp) # save registers on stack + stws,ma brindex,4(sp) # save registers on stack + stws,ma sign,4(sp) # save registers on stack + stws,ma pc,4(sp) # save registers on stack + stws,ma pm,4(sp) # save registers on stack +# +# Start multiply process +# + ldws 0(arg1),op2 # get multiplier + ldws 0(arg0),op1 # get multiplicand + addi -1,gr0,pm # initialize pm to 111...1 + comb,< op2,gr0,mpyb # br. if multiplier < 0 + xor op2,op1,sign # sign(0) = sign of product +mpy1 comb,< op1,gr0,mpya # br. if multiplicand < 0 + addi 0,gr0,pu # clear product + addib,= 0,op1,fini0 # op1 = 0, product = 0 +mpy2 addi 1,gr0,pc # initialize pc to 00...01 + movib,tr 8,cnt,mloop # set count for mpy loop + extru op2,31,4,brindex # 4 bits as index into table +# + .align 8 +# + b sh4c # br. if sign overflow +sh4n shd pu,pl,4,pl # shift product right 4 bits + addib,<= -1,cnt,mulend # reduce count by 1, exit if + extru pu,27,28,pu # <= zero +# +mloop blr brindex,gr0 # br. into table + # entries of 2 words + extru op2,27,4,brindex # next 4 bits into index +# +# +# branch table for the multiplication process with four multiplier bits +# +mtable # two words per entry +# +# ---- bits = 0000 ---- shift product 4 bits ------------------------------- +# + b sh4n+4 # just shift partial + shd pu,pl,4,pl # product right 4 bits +# +# ---- bits = 0001 ---- add op1, then shift 4 bits +# + addb,tr op1,pu,sh4n+4 # add op1 to product, to shift + shd pu,pl,4,pl # product right 4 bits +# +# ---- bits = 0010 ---- add op1, add op1, then shift 4 bits +# + addb,tr op1,pu,sh4n # add 2*op1, to shift + addb,uv op1,pu,sh4c # product right 4 bits +# +# ---- bits = 0011 ---- add op1, add 2*op1, shift 4 bits +# + addb,tr op1,pu,sh4n-4 # add op1 & 2*op1, shift + sh1add,nsv op1,pu,pu # product right 4 bits +# +# ---- bits = 0100 ---- shift 2, add op1, shift 2 +# + b sh2sa + shd pu,pl,2,pl # shift product 2 bits +# +# ---- bits = 0101 ---- add op1, shift 2, add op1, and shift 2 again +# + addb,tr op1,pu,sh2us # add op1 to product + shd pu,pl,2,pl # shift 2 bits +# +# ---- bits = 0110 ---- add op1, add op1, shift 2, add op1, and shift 2 again +# + addb,tr op1,pu,sh2c # add 2*op1, to shift 2 bits + addb,nuv op1,pu,sh2us # br. if not overflow +# +# ---- bits = 0111 ---- subtract op1, shift 3, add op1, and shift 1 +# + b sh3s + sub pu,op1,pu # subtract op1, br. to sh3s + +# +# ---- bits = 1000 ---- shift 3, add op1, shift 1 +# + b sh3sa + shd pu,pl,3,pl # shift product right 3 bits +# +# ---- bits = 1001 ---- add op1, shift 3, add op1, shift 1 +# + addb,tr op1,pu,sh3us # add op1, to shift 3, add op1, + shd pu,pl,3,pl # and shift 1 +# +# ---- bits = 1010 ---- add op1, add op1, shift 3, add op1, shift 1 +# + addb,tr op1,pu,sh3c # add 2*op1, to shift 3 bits + addb,nuv op1,pu,sh3us # br. if no overflow +# +# ---- bits = 1011 ---- add -op1, shift 2, add -op1, shift 2, inc. next index +# + addib,tr 1,brindex,sh2s # add 1 to index, subtract op1, + sub pu,op1,pu # shift 2 with minus sign +# +# ---- bits = 1100 ---- shift 2, subtract op1, shift 2, increment next index +# + addib,tr 1,brindex,sh2sb # add 1 to index, to shift + shd pu,pl,2,pl # shift right 2 bits signed +# +# ---- bits = 1101 ---- add op1, shift 2, add -op1, shift 2 +# + addb,tr op1,pu,sh2ns # add op1, to shift 2 + shd pu,pl,2,pl # right 2 unsigned, etc. +# +# ---- bits = 1110 ---- shift 1 signed, add -op1, shift 3 signed +# + addib,tr 1,brindex,sh1sa # add 1 to index, to shift + shd pu,pl,1,pl # shift 1 bit +# +# ---- bits = 1111 ---- add -op1, shift 4 signed +# + addib,tr 1,brindex,sh4s # add 1 to index, subtract op1, + sub pu,op1,pu # to shift 4 signed + +# +# ---- bits = 10000 ---- shift 4 signed +# + addib,tr 1,brindex,sh4s+4 # add 1 to index + shd pu,pl,4,pl # shift 4 signed +# +# ---- end of table --------------------------------------------------------- +# +sh4s shd pu,pl,4,pl + addib,tr -1,cnt,mloop # loop (count > 0 always here) + shd pm,pu,4,pu # shift 4, minus signed +# +sh4c addib,> -1,cnt,mloop # decrement count, loop if > 0 + shd pc,pu,4,pu # shift 4 with overflow + b signs # end of multiply + bb,>=,n sign,0,fini # test sign of procduct +# +mpyb add,= op2,op2,gr0 # if <> 0, back to main sect. + b mpy1 + sub 0,op2,op2 # op2 = |multiplier| + add,>= op1,gr0,gr0 # if op1 < 0, invert sign, + xor pm,sign,sign # for correct result +# +# special case for multiplier = -2**31, op1 = signed multiplicand +# or multiplicand = -2**31, op1 = signed multiplier +# + shd op1,0,1,pl # shift op1 left 31 bits +mmax extrs op1,30,31,pu + b signs # negate product (if needed) + bb,>=,n sign,0,fini # test sign of product +# +mpya add,= op1,op1,gr0 # op1 = -2**31, special case + b mpy2 + sub 0,op1,op1 # op1 = |multiplicand| + add,>= op2,gr0,gr0 # if op2 < 0, invert sign, + xor pm,sign,sign # for correct result + movb,tr op2,op1,mmax # use op2 as multiplicand + shd op1,0,1,pl # shift it left 31 bits +# +sh3c shd pu,pl,3,pl # shift product 3 bits + shd pc,pu,3,pu # shift 3 signed + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3us extru pu,28,29,pu # shift 3 unsigned + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3sa extrs pu,28,29,pu # shift 3 signed + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3s shd pu,pl,3,pl # shift 3 minus signed + shd pm,pu,3,pu + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh1 addib,> -1,cnt,mloop # loop if count > 0 + extru pu,30,31,pu + b signs # end of multiply + bb,>=,n sign,0,fini # test sign of product +# +sh2ns addib,tr 1,brindex,sh2sb+4 # increment index + extru pu,29,30,pu # shift unsigned +# +sh2s shd pu,pl,2,pl # shift with minus sign + shd pm,pu,2,pu # + sub pu,op1,pu # subtract op1 + shd pu,pl,2,pl # shift with minus sign + addib,tr -1,cnt,mloop # decrement count, loop + shd pm,pu,2,pu # shift with minus sign + # count never reaches 0 here +# +sh2sb extrs pu,29,30,pu # shift 2 signed + sub pu,op1,pu # subtract op1 from product + shd pu,pl,2,pl # shift with minus sign + addib,tr -1,cnt,mloop # decrement count, loop + shd pm,pu,2,pu # shift with minus sign + # count never reaches 0 here +# +sh1sa extrs pu,30,31,pu # signed + sub pu,op1,pu # subtract op1 from product + shd pu,pl,3,pl # shift 3 with minus sign + addib,tr -1,cnt,mloop # dec. count, to loop + shd pm,pu,3,pu # count never reaches 0 here +# +fini0 movib,tr,n 0,pl,fini # product = 0 as op1 = 0 +# +sh2us extru pu,29,30,pu # shift 2 unsigned + addb,tr op1,pu,sh2a # add op1 + shd pu,pl,2,pl # shift 2 bits +# +sh2c shd pu,pl,2,pl + shd pc,pu,2,pu # shift with carry + addb,tr op1,pu,sh2a # add op1 to product + shd pu,pl,2,pl # br. to sh2 to shift pu +# +sh2sa extrs pu,29,30,pu # shift with sign + addb,tr op1,pu,sh2a # add op1 to product + shd pu,pl,2,pl # br. to sh2 to shift pu +# +sh2a addib,> -1,cnt,mloop # loop if count > 0 + extru pu,29,30,pu +# +mulend bb,>=,n sign,0,fini # test sign of product +signs sub 0,pl,pl # negate product if sign + subb 0,pu,pu # is negative +# +# finish +# +fini stws pu,0(arg2) # save high part of result + stws pl,4(arg2) # save low part of result + + ldws,mb -4(sp),pm # restore registers + ldws,mb -4(sp),pc # restore registers + ldws,mb -4(sp),sign # restore registers + ldws,mb -4(sp),brindex # restore registers + ldws,mb -4(sp),cnt # restore registers + ldws,mb -4(sp),op1 # restore registers + ldws,mb -4(sp),pl # restore registers + bv 0(rp) # return + ldws,mb -4(sp),pu # restore registers + + .procend + .end diff --git a/sys/arch/hppa/spmath/impyu.S b/sys/arch/hppa/spmath/impyu.S new file mode 100644 index 00000000000..ce7e995601f --- /dev/null +++ b/sys/arch/hppa/spmath/impyu.S @@ -0,0 +1,322 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/impyu.S,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:02 $ + */ + +#include <machine/asm.h> + +/**************************************************************************** + * + *Implement an integer multiply routine for 32-bit operands and 64-bit product + * with operand values of zero (multiplicand only) and 2**32reated specially. + * The algorithm uses the multiplier, four bits at a time, from right to left, + * to generate partial product. Execution speed is more important than program + * size in this implementation. + * + *****************************************************************************/ +# +# Definitions - General registers +# +gr0 .equ 0 # General register zero +pu .equ 3 # upper part of product +pl .equ 4 # lower part of product +op2 .equ 4 # multiplier +op1 .equ 5 # multiplicand +cnt .equ 6 # count in multiply +brindex .equ 7 # index into the br. table +saveop2 .equ 8 # save op2 if high bit of multiplicand + # is set +pc .equ 9 # carry bit of product, = 00...01 +pm .equ 10 # value of -1 used in shifting +temp .equ 6 + +#**************************************************************************** + .export impyu,entry + .space $TEXT$ + .subspa $CODE$ + .align 4 + .proc + .callinfo +# +#**************************************************************************** +impyu stws,ma pu,4(sp) # save registers on stack + stws,ma pl,4(sp) # save registers on stack + stws,ma op1,4(sp) # save registers on stack + stws,ma cnt,4(sp) # save registers on stack + stws,ma brindex,4(sp) # save registers on stack + stws,ma saveop2,4(sp) # save registers on stack + stws,ma pc,4(sp) # save registers on stack + stws,ma pm,4(sp) # save registers on stack +# +# Start multiply process +# + ldws 0(arg0),op1 # get multiplicand + ldws 0(arg1),op2 # get multiplier + addib,= 0,op1,fini0 # op1 = 0, product = 0 + addi 0,gr0,pu # clear product + bb,>= op1,0,mpy1 # test msb of multiplicand + addi 0,gr0,saveop2 # clear saveop2 +# +# msb of multiplicand is set so will save multiplier for a final +# addition into the result +# + extru,= op1,31,31,op1 # clear msb of multiplicand + b mpy1 # if op1 < 2**32, start multiply + add op2,gr0,saveop2 # save op2 in saveop2 + shd gr0,op2,1,pu # shift op2 left 31 for result + b fini # go to finish + shd op2,gr0,1,pl +# +mpy1 addi -1,gr0,pm # initialize pm to 111...1 + addi 1,gr0,pc # initialize pc to 00...01 + movib,tr 8,cnt,mloop # set count for mpy loop + extru op2,31,4,brindex # 4 bits as index into table +# + .align 8 +# + b sh4c # br. if sign overflow +sh4n shd pu,pl,4,pl # shift product right 4 bits + addib,<= -1,cnt,mulend # reduce count by 1, exit if + extru pu,27,28,pu # <= zero +# +mloop blr brindex,gr0 # br. into table + # entries of 2 words + extru op2,27,4,brindex # next 4 bits into index +# +# +# branch table for the multiplication process with four multiplier bits +# +mtable # two words per entry +# +# ---- bits = 0000 ---- shift product 4 bits ------------------------------- +# + b sh4n+4 # just shift partial + shd pu,pl,4,pl # product right 4 bits +# +# ---- bits = 0001 ---- add op1, then shift 4 bits +# + addb,tr op1,pu,sh4n+4 # add op1 to product, to shift + shd pu,pl,4,pl # product right 4 bits +# +# ---- bits = 0010 ---- add op1, add op1, then shift 4 bits +# + addb,tr op1,pu,sh4n # add 2*op1, to shift + addb,uv op1,pu,sh4c # product right 4 bits +# +# ---- bits = 0011 ---- add op1, add 2*op1, shift 4 bits +# + addb,tr op1,pu,sh4n-4 # add op1 & 2*op1, shift + sh1add,nuv op1,pu,pu # product right 4 bits +# +# ---- bits = 0100 ---- shift 2, add op1, shift 2 +# + b sh2sa + shd pu,pl,2,pl # shift product 2 bits +# +# ---- bits = 0101 ---- add op1, shift 2, add op1, and shift 2 again +# + addb,tr op1,pu,sh2us # add op1 to product + shd pu,pl,2,pl # shift 2 bits +# +# ---- bits = 0110 ---- add op1, add op1, shift 2, add op1, and shift 2 again +# + addb,tr op1,pu,sh2c # add 2*op1, to shift 2 bits + addb,nuv op1,pu,sh2us # br. if not overflow +# +# ---- bits = 0111 ---- subtract op1, shift 3, add op1, and shift 1 +# + b sh3s + sub pu,op1,pu # subtract op1, br. to sh3s + +# +# ---- bits = 1000 ---- shift 3, add op1, shift 1 +# + b sh3sa + shd pu,pl,3,pl # shift product right 3 bits +# +# ---- bits = 1001 ---- add op1, shift 3, add op1, shift 1 +# + addb,tr op1,pu,sh3us # add op1, to shift 3, add op1, + shd pu,pl,3,pl # and shift 1 +# +# ---- bits = 1010 ---- add op1, add op1, shift 3, add op1, shift 1 +# + addb,tr op1,pu,sh3c # add 2*op1, to shift 3 bits + addb,nuv op1,pu,sh3us # br. if no overflow +# +# ---- bits = 1011 ---- add -op1, shift 2, add -op1, shift 2, inc. next index +# + addib,tr 1,brindex,sh2s # add 1 to index, subtract op1, + sub pu,op1,pu # shift 2 with minus sign +# +# ---- bits = 1100 ---- shift 2, subtract op1, shift 2, increment next index +# + addib,tr 1,brindex,sh2sb # add 1 to index, to shift + shd pu,pl,2,pl # shift right 2 bits signed +# +# ---- bits = 1101 ---- add op1, shift 2, add -op1, shift 2 +# + addb,tr op1,pu,sh2ns # add op1, to shift 2 + shd pu,pl,2,pl # right 2 unsigned, etc. +# +# ---- bits = 1110 ---- shift 1 signed, add -op1, shift 3 signed +# + addib,tr 1,brindex,sh1sa # add 1 to index, to shift + shd pu,pl,1,pl # shift 1 bit +# +# ---- bits = 1111 ---- add -op1, shift 4 signed +# + addib,tr 1,brindex,sh4s # add 1 to index, subtract op1, + sub pu,op1,pu # to shift 4 signed + +# +# ---- bits = 10000 ---- shift 4 signed +# + addib,tr 1,brindex,sh4s+4 # add 1 to index + shd pu,pl,4,pl # shift 4 signed +# +# ---- end of table --------------------------------------------------------- +# +sh4s shd pu,pl,4,pl + addib,> -1,cnt,mloop # decrement count, loop if > 0 + shd pm,pu,4,pu # shift 4, minus signed + addb,tr op1,pu,lastadd # do one more add, then finish + addb,=,n saveop2,gr0,fini # check saveop2 +# +sh4c addib,> -1,cnt,mloop # decrement count, loop if > 0 + shd pc,pu,4,pu # shift 4 with overflow + b lastadd # end of multiply + addb,=,n saveop2,gr0,fini # check saveop2 +# +sh3c shd pu,pl,3,pl # shift product 3 bits + shd pc,pu,3,pu # shift 3 signed + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3us extru pu,28,29,pu # shift 3 unsigned + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3sa extrs pu,28,29,pu # shift 3 signed + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh3s shd pu,pl,3,pl # shift 3 minus signed + shd pm,pu,3,pu + addb,tr op1,pu,sh1 # add op1, to shift 1 bit + shd pu,pl,1,pl +# +sh1 addib,> -1,cnt,mloop # loop if count > 0 + extru pu,30,31,pu + b lastadd # end of multiply + addb,=,n saveop2,gr0,fini # check saveop2 +# +sh2ns addib,tr 1,brindex,sh2sb+4 # increment index + extru pu,29,30,pu # shift unsigned +# +sh2s shd pu,pl,2,pl # shift with minus sign + shd pm,pu,2,pu # + sub pu,op1,pu # subtract op1 + shd pu,pl,2,pl # shift with minus sign + addib,> -1,cnt,mloop # decrement count, loop if > 0 + shd pm,pu,2,pu # shift with minus sign + addb,tr op1,pu,lastadd # do one more add, then finish + addb,=,n saveop2,gr0,fini # check saveop2 +# +sh2sb extrs pu,29,30,pu # shift 2 signed + sub pu,op1,pu # subtract op1 from product + shd pu,pl,2,pl # shift with minus sign + addib,> -1,cnt,mloop # decrement count, loop if > 0 + shd pm,pu,2,pu # shift with minus sign + addb,tr op1,pu,lastadd # do one more add, then finish + addb,=,n saveop2,gr0,fini # check saveop2 +# +sh1sa extrs pu,30,31,pu # signed + sub pu,op1,pu # subtract op1 from product + shd pu,pl,3,pl # shift 3 with minus sign + addib,> -1,cnt,mloop # decrement count, loop if >0 + shd pm,pu,3,pu + addb,tr op1,pu,lastadd # do one more add, then finish + addb,=,n saveop2,gr0,fini # check saveop2 +# +fini0 movib,tr 0,pl,fini # product = 0 as op1 = 0 + stws pu,0(arg2) # save high part of result +# +sh2us extru pu,29,30,pu # shift 2 unsigned + addb,tr op1,pu,sh2a # add op1 + shd pu,pl,2,pl # shift 2 bits +# +sh2c shd pu,pl,2,pl + shd pc,pu,2,pu # shift with carry + addb,tr op1,pu,sh2a # add op1 to product + shd pu,pl,2,pl # br. to sh2 to shift pu +# +sh2sa extrs pu,29,30,pu # shift with sign + addb,tr op1,pu,sh2a # add op1 to product + shd pu,pl,2,pl # br. to sh2 to shift pu +# +sh2a addib,> -1,cnt,mloop # loop if count > 0 + extru pu,29,30,pu +# +mulend addb,=,n saveop2,gr0,fini # check saveop2 +lastadd shd saveop2,gr0,1,temp # if saveop2 <> 0, shift it + shd gr0,saveop2,1,saveop2 # left 31 and add to result + add pl,temp,pl + addc pu,saveop2,pu +# +# finish +# +fini stws pu,0(arg2) # save high part of result + stws pl,4(arg2) # save low part of result + + ldws,mb -4(sp),pm # restore registers + ldws,mb -4(sp),pc # restore registers + ldws,mb -4(sp),saveop2 # restore registers + ldws,mb -4(sp),brindex # restore registers + ldws,mb -4(sp),cnt # restore registers + ldws,mb -4(sp),op1 # restore registers + ldws,mb -4(sp),pl # restore registers + bv 0(rp) # return + ldws,mb -4(sp),pu # restore registers + + .procend + .end diff --git a/sys/arch/hppa/spmath/md.h b/sys/arch/hppa/spmath/md.h new file mode 100644 index 00000000000..535d02f8f32 --- /dev/null +++ b/sys/arch/hppa/spmath/md.h @@ -0,0 +1,93 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)md.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:02 $ + * $Locker: $ + * + */ + +/***************************************************************** + * Muliply/Divide SFU Internal State * + *****************************************************************/ +struct mdsfu_register { + int rslt_hi, + rslt_lo, + ovflow; + }; + +#define result_hi result->rslt_hi +#define result_lo result->rslt_lo +#define overflow result->ovflow + +/* + * Types + */ +typedef int VOID; +typedef int boolean; + + +/* + * Constants + */ + +#undef FALSE +#define FALSE 0 + +#undef TRUE +#define TRUE (!FALSE) + +#undef NIL +#define NIL 0 + +#define WORD_LEN 32 +#define BIT0 1<<31 +#define BIT28 0x8 +#define BIT29 0x4 +#define BIT30 0x2 +#define BIT31 0x1 + + +/* + * Structures + */ + +struct md_state { + int resulthi, /* high word of result */ + resultlo; /* low word of result */ +}; diff --git a/sys/arch/hppa/spmath/mpyaccs.c b/sys/arch/hppa/spmath/mpyaccs.c new file mode 100644 index 00000000000..ce5f2670830 --- /dev/null +++ b/sys/arch/hppa/spmath/mpyaccs.c @@ -0,0 +1,69 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpyaccs.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:03 $ + */ + + +#include "../spmath/md.h" + +VOID mpyaccs(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + struct mdsfu_register temp; + int carry, sign; + + impys(&opnd1,&opnd2,&temp); + + /* get result of low word add, and check for carry out */ + if ((result_lo += (unsigned)temp.rslt_lo) < (unsigned)temp.rslt_lo) + carry = 1; + else carry = 0; + + /* get result of high word add, and determine overflow status */ + sign = result_hi ^ temp.rslt_hi; + result_hi += temp.rslt_hi + carry; + if (sign >= 0 && (temp.rslt_hi ^ result_hi) < 0) overflow = TRUE; + + return; +} diff --git a/sys/arch/hppa/spmath/mpyaccu.c b/sys/arch/hppa/spmath/mpyaccu.c new file mode 100644 index 00000000000..e0da85e30a8 --- /dev/null +++ b/sys/arch/hppa/spmath/mpyaccu.c @@ -0,0 +1,68 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpyaccu.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:03 $ + */ + + +#include "../spmath/md.h" + +VOID mpyaccu(opnd1,opnd2,result) + +unsigned int opnd1, opnd2; +struct mdsfu_register *result; +{ + struct mdsfu_register temp; + int carry; + + impyu(&opnd1,&opnd2,&temp); + + /* get result of low word add, and check for carry out */ + if ((result_lo += (unsigned)temp.rslt_lo) < (unsigned)temp.rslt_lo) + carry = 1; + else carry = 0; + + /* get result of high word add, and determine overflow status */ + if ((result_hi += (unsigned)temp.rslt_hi + carry) < + (unsigned)temp.rslt_hi) overflow = TRUE; + + return; +} diff --git a/sys/arch/hppa/spmath/mpys.c b/sys/arch/hppa/spmath/mpys.c new file mode 100644 index 00000000000..8b0d5063b50 --- /dev/null +++ b/sys/arch/hppa/spmath/mpys.c @@ -0,0 +1,60 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpys.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:04 $ + */ + + +#include "../spmath/md.h" + +VOID mpys(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + impys(&opnd1,&opnd2,result); + + /* determine overflow status */ + if ((result_hi == 0 && result_lo >= 0) || + (result_hi == -1 && result_lo < 0)) overflow = FALSE; + else overflow = TRUE; + return; +} diff --git a/sys/arch/hppa/spmath/mpyscv.c b/sys/arch/hppa/spmath/mpyscv.c new file mode 100644 index 00000000000..7e020eb4aa6 --- /dev/null +++ b/sys/arch/hppa/spmath/mpyscv.c @@ -0,0 +1,56 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpyscv.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:04 $ + */ + + +#include "../spmath/md.h" + +VOID mpyscv(opnd1,opnd2,result) + +int opnd1, opnd2; +struct mdsfu_register *result; +{ + impys(&opnd1,&opnd2,result); + overflow = FALSE; + return; +} diff --git a/sys/arch/hppa/spmath/mpyu.c b/sys/arch/hppa/spmath/mpyu.c new file mode 100644 index 00000000000..e2ad3591ca4 --- /dev/null +++ b/sys/arch/hppa/spmath/mpyu.c @@ -0,0 +1,58 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpyu.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:04 $ + */ + + +#include "../spmath/md.h" + +VOID mpyu(opnd1,opnd2,result) + +unsigned int opnd1, opnd2; +struct mdsfu_register *result; +{ + impyu(&opnd1,&opnd2,result); + /* determine overflow status */ + if (result_hi) overflow = TRUE; + else overflow = FALSE; + return; +} diff --git a/sys/arch/hppa/spmath/mpyucv.c b/sys/arch/hppa/spmath/mpyucv.c new file mode 100644 index 00000000000..c3fb9f4036e --- /dev/null +++ b/sys/arch/hppa/spmath/mpyucv.c @@ -0,0 +1,56 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/mpyucv.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:05 $ + */ + + +#include "../spmath/md.h" + +VOID mpyucv(opnd1,opnd2,result) + +unsigned int opnd1, opnd2; +struct mdsfu_register *result; +{ + impyu(&opnd1,&opnd2,result); + overflow = FALSE; + return; +} diff --git a/sys/arch/hppa/spmath/quad_float.h b/sys/arch/hppa/spmath/quad_float.h new file mode 100644 index 00000000000..e22403729fd --- /dev/null +++ b/sys/arch/hppa/spmath/quad_float.h @@ -0,0 +1,102 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)quad_float.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:05 $ + * $Locker: $ + * + */ +/****************************** + * Quad precision functions * + ******************************/ + +/* 32-bit word grabing functions */ +#define Quad_firstword(value) Qallp1(value) +#define Quad_secondword(value) Qallp2(value) +#define Quad_thirdword(value) Qallp3(value) +#define Quad_fourthword(value) Qallp4(value) + + +/* This magnitude comparison uses the signless first words and + * the regular part2 words. The comparison is graphically: + * + * 1st greater? ----------->| + * | + * 1st less?-----------------+------->| + * | | + * 2nd greater?------------->| | + * | | + * 2nd less?-----------------+------->| + * | | + * 3rd greater?------------->| | + * | | + * 3rd less?-----------------+------->| + * | | + * 4th greater or equal?---->| | + * | | + * False True + */ +#define Quad_ismagnitudeless(leftp3,leftp4,rightp1,rightp2,rightp3,rightp4,signlessleft,signlessright) \ +/* Quad_floating_point left, right; * \ + * unsigned int signlessleft, signlessright; */ \ + ( signlessleft<=signlessright && \ + (signlessleft<signlessright || (Qallp2(leftp2)<=Qallp2(rightp2) && \ + (Qallp2(leftp2)<Qallp2(rightp2) || (Qallp3(leftp3)<=Qallp3(rightp3) && \ + (Qallp3(leftp3)<Qallp3(rightp3) || Qallp4(leftp4)<Qallp4(rightp4))))))) + +#define Quad_xor_to_intp1(leftp1,rightp1,result) \ + /* quad_floating_point left, right; \ + * unsigned int result; */ \ + result = Qallp1(leftp1) XOR Qallp1(rightp1); + +#define Quad_xor_from_intp1(leftp1,rightp1,result) \ + /* quad_floating_point right, result; \ + * unsigned int left; */ \ + Qallp1(resultp1) = left XOR Qallp1(rightp1) + +#define Quad_swap_lower(leftp1,leftp2,leftp3,leftp4,rightp1,rightp2,rightp3,rightp4) \ + /* quad_floating_point left, right; */ \ + Qallp2(leftp2) = Qallp2(leftp2) XOR Qallp2(rightp2) \ + Qallp2(rightp2) = Qallp2(leftp2) XOR Qallp2(rightp2) \ + Qallp2(leftp2) = Qallp2(leftp2) XOR Qallp2(rightp2) \ + Qallp3(leftp3) = Qallp3(leftp3) XOR Qallp3(rightp3) \ + Qallp3(rightp3) = Qallp3(leftp3) XOR Qallp3(rightp3) \ + Qallp3(leftp3) = Qallp3(leftp3) XOR Qallp3(rightp3) \ + Qallp4(leftp4) = Qallp4(leftp4) XOR Qallp4(rightp4) \ + Qallp4(rightp4) = Qallp4(leftp4) XOR Qallp4(rightp4) \ + Qallp4(leftp4) = Qallp4(leftp4) XOR Qallp4(rightp4) diff --git a/sys/arch/hppa/spmath/setovfl.c b/sys/arch/hppa/spmath/setovfl.c new file mode 100644 index 00000000000..ecf06a13c52 --- /dev/null +++ b/sys/arch/hppa/spmath/setovfl.c @@ -0,0 +1,118 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/Attic/setovfl.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:06 $ + */ + + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" +#include "../spmath/dbl_float.h" + +sgl_floating_point sgl_setoverflow(sign) + +unsigned int sign; +{ + sgl_floating_point result; + + /* set result to infinity or largest number */ + /* ignore for now + switch (Rounding_mode()) { + case ROUNDPLUS: + if (sign) { + Sgl_setlargestnegative(result); + } + else { + Sgl_setinfinitypositive(result); + } + break; + case ROUNDMINUS: + if (sign==0) { + Sgl_setlargestpositive(result); + } + else { + Sgl_setinfinitynegative(result); + } + break; + case ROUNDNEAREST: + Sgl_setinfinity(result,sign); + break; + case ROUNDZERO: + Sgl_setlargest(result,sign); + } + return(result); + */ +} + +dbl_floating_point dbl_setoverflow(sign) + +unsigned int sign; +{ + dbl_floating_point result; + + /* set result to infinity or largest number */ + /* ignore for now + switch (Rounding_mode()) { + case ROUNDPLUS: + if (sign) { + Dbl_setlargestnegative(result); + } + else { + Dbl_setinfinitypositive(result); + } + break; + case ROUNDMINUS: + if (sign==0) { + Dbl_setlargestpositive(result); + } + else { + Dbl_setinfinitynegative(result); + } + break; + case ROUNDNEAREST: + Dbl_setinfinity(result,sign); + break; + case ROUNDZERO: + Dbl_setlargest(result,sign); + } + return(result); + */ +} diff --git a/sys/arch/hppa/spmath/sfadd.c b/sys/arch/hppa/spmath/sfadd.c new file mode 100644 index 00000000000..c1a3c5555fd --- /dev/null +++ b/sys/arch/hppa/spmath/sfadd.c @@ -0,0 +1,518 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfadd.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:06 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single_add: add two single precision values. + */ +sgl_fadd(leftptr, rightptr, dstptr, status) + sgl_floating_point *leftptr, *rightptr, *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); + } diff --git a/sys/arch/hppa/spmath/sfcmp.c b/sys/arch/hppa/spmath/sfcmp.c new file mode 100644 index 00000000000..d1e7e73c69a --- /dev/null +++ b/sys/arch/hppa/spmath/sfcmp.c @@ -0,0 +1,155 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfcmp.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:06 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * sgl_cmp: compare two values + */ +sgl_fcmp(leftptr, rightptr, cond, status) + sgl_floating_point *leftptr, *rightptr; + unsigned int cond; /* The predicate to be tested */ + unsigned int *status; + { + 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); + } diff --git a/sys/arch/hppa/spmath/sfdiv.c b/sys/arch/hppa/spmath/sfdiv.c new file mode 100644 index 00000000000..e6fc937f7bb --- /dev/null +++ b/sys/arch/hppa/spmath/sfdiv.c @@ -0,0 +1,396 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfdiv.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:07 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single Precision Floating-point Divide + */ + +sgl_fdiv(srcptr1,srcptr2,dstptr,status) + +sgl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/sfmpy.c b/sys/arch/hppa/spmath/sfmpy.c new file mode 100644 index 00000000000..11a83ef9658 --- /dev/null +++ b/sys/arch/hppa/spmath/sfmpy.c @@ -0,0 +1,381 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfmpy.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:07 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single Precision Floating-point Multiply + */ + +sgl_fmpy(srcptr1,srcptr2,dstptr,status) + +sgl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/sfrem.c b/sys/arch/hppa/spmath/sfrem.c new file mode 100644 index 00000000000..515b34ea280 --- /dev/null +++ b/sys/arch/hppa/spmath/sfrem.c @@ -0,0 +1,294 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfrem.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:07 $ + */ + + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single Precision Floating-point Remainder + */ + +sgl_frem(srcptr1,srcptr2,dstptr,status) + +sgl_floating_point *srcptr1, *srcptr2, *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); +} diff --git a/sys/arch/hppa/spmath/sfsqrt.c b/sys/arch/hppa/spmath/sfsqrt.c new file mode 100644 index 00000000000..938d1a2c13e --- /dev/null +++ b/sys/arch/hppa/spmath/sfsqrt.c @@ -0,0 +1,187 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfsqrt.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:08 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single Floating-point Square Root + */ + +/*ARGSUSED*/ +sgl_fsqrt(srcptr,nullptr,dstptr,status) + +sgl_floating_point *srcptr, *dstptr; +unsigned int *nullptr, *status; +{ + register unsigned int src, result; + register int src_exponent, 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); +} diff --git a/sys/arch/hppa/spmath/sfsub.c b/sys/arch/hppa/spmath/sfsub.c new file mode 100644 index 00000000000..242978ce246 --- /dev/null +++ b/sys/arch/hppa/spmath/sfsub.c @@ -0,0 +1,521 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* $Source: /cvs/OpenBSD/src/sys/arch/hppa/spmath/sfsub.c,v $ + * $Revision: 1.1 $ $Author: mickey $ + * $State: Exp $ $Locker: $ + * $Date: 1998/06/23 20:34:08 $ + */ + +#include "../spmath/float.h" +#include "../spmath/sgl_float.h" + +/* + * Single_subtract: subtract two single precision values. + */ +sgl_fsub(leftptr, rightptr, dstptr, status) + sgl_floating_point *leftptr, *rightptr, *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); + } diff --git a/sys/arch/hppa/spmath/sgl_float.h b/sys/arch/hppa/spmath/sgl_float.h new file mode 100644 index 00000000000..ae2a2f36acf --- /dev/null +++ b/sys/arch/hppa/spmath/sgl_float.h @@ -0,0 +1,334 @@ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * pmk1.1 + */ +/* + * (c) Copyright 1986 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ +/* + * @(#)sgl_float.h: $Revision: 1.1 $ $Date: 1998/06/23 20:34:09 $ + * $Locker: $ + * + */ +/****************************** + * Single precision functions * + ******************************/ + +/* 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)|~(1<<31)) & Sall(src1dst) +#define Sgl_or_signs( src1dst, src2) \ + Sall(src1dst) = (Sall(src2)&(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) &= ~(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) & (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))) \ + | (1<<31) +#define Sgl_setinfinity(sgl_value,sign) \ + Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \ + (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) = 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 ) | (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) = 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) & (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); \ + } |