mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
8.5 KiB
296 lines
8.5 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* Linux/PA-RISC Project (http://www.parisc-linux.org/) |
|
* |
|
* Floating-point emulation code |
|
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]> |
|
*/ |
|
/* |
|
* BEGIN_DESC |
|
* |
|
* File: |
|
* @(#) pa/spmath/fcnvff.c $Revision: 1.1 $ |
|
* |
|
* Purpose: |
|
* Single Floating-point to Double Floating-point |
|
* Double Floating-point to Single Floating-point |
|
* |
|
* External Interfaces: |
|
* dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) |
|
* sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) |
|
* |
|
* Internal Interfaces: |
|
* |
|
* Theory: |
|
* <<please update with a overview of the operation of this file>> |
|
* |
|
* END_DESC |
|
*/ |
|
|
|
|
|
#include "float.h" |
|
#include "sgl_float.h" |
|
#include "dbl_float.h" |
|
#include "cnv_float.h" |
|
|
|
/* |
|
* Single Floating-point to Double Floating-point |
|
*/ |
|
/*ARGSUSED*/ |
|
int |
|
sgl_to_dbl_fcnvff( |
|
sgl_floating_point *srcptr, |
|
unsigned int *nullptr, |
|
dbl_floating_point *dstptr, |
|
unsigned int *status) |
|
{ |
|
register unsigned int src, resultp1, resultp2; |
|
register int src_exponent; |
|
|
|
src = *srcptr; |
|
src_exponent = Sgl_exponent(src); |
|
Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ |
|
/* |
|
* Test for NaN or infinity |
|
*/ |
|
if (src_exponent == SGL_INFINITY_EXPONENT) { |
|
/* |
|
* determine if NaN or infinity |
|
*/ |
|
if (Sgl_iszero_mantissa(src)) { |
|
/* |
|
* is infinity; want to return double infinity |
|
*/ |
|
Dbl_setinfinity_exponentmantissa(resultp1,resultp2); |
|
Dbl_copytoptr(resultp1,resultp2,dstptr); |
|
return(NOEXCEPTION); |
|
} |
|
else { |
|
/* |
|
* is NaN; signaling or quiet? |
|
*/ |
|
if (Sgl_isone_signaling(src)) { |
|
/* trap if INVALIDTRAP enabled */ |
|
if (Is_invalidtrap_enabled()) |
|
return(INVALIDEXCEPTION); |
|
/* make NaN quiet */ |
|
else { |
|
Set_invalidflag(); |
|
Sgl_set_quiet(src); |
|
} |
|
} |
|
/* |
|
* NaN is quiet, return as double NaN |
|
*/ |
|
Dbl_setinfinity_exponent(resultp1); |
|
Sgl_to_dbl_mantissa(src,resultp1,resultp2); |
|
Dbl_copytoptr(resultp1,resultp2,dstptr); |
|
return(NOEXCEPTION); |
|
} |
|
} |
|
/* |
|
* Test for zero or denormalized |
|
*/ |
|
if (src_exponent == 0) { |
|
/* |
|
* determine if zero or denormalized |
|
*/ |
|
if (Sgl_isnotzero_mantissa(src)) { |
|
/* |
|
* is denormalized; want to normalize |
|
*/ |
|
Sgl_clear_signexponent(src); |
|
Sgl_leftshiftby1(src); |
|
Sgl_normalize(src,src_exponent); |
|
Sgl_to_dbl_exponent(src_exponent,resultp1); |
|
Sgl_to_dbl_mantissa(src,resultp1,resultp2); |
|
} |
|
else { |
|
Dbl_setzero_exponentmantissa(resultp1,resultp2); |
|
} |
|
Dbl_copytoptr(resultp1,resultp2,dstptr); |
|
return(NOEXCEPTION); |
|
} |
|
/* |
|
* No special cases, just complete the conversion |
|
*/ |
|
Sgl_to_dbl_exponent(src_exponent, resultp1); |
|
Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); |
|
Dbl_copytoptr(resultp1,resultp2,dstptr); |
|
return(NOEXCEPTION); |
|
} |
|
|
|
/* |
|
* Double Floating-point to Single Floating-point |
|
*/ |
|
/*ARGSUSED*/ |
|
int |
|
dbl_to_sgl_fcnvff( |
|
dbl_floating_point *srcptr, |
|
unsigned int *nullptr, |
|
sgl_floating_point *dstptr, |
|
unsigned int *status) |
|
{ |
|
register unsigned int srcp1, srcp2, result; |
|
register int src_exponent, dest_exponent, dest_mantissa; |
|
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; |
|
register boolean lsb_odd = FALSE; |
|
boolean is_tiny = FALSE; |
|
|
|
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); |
|
}
|
|
|