1*660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Floating-point emulation code
61da177e4SLinus Torvalds * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds * BEGIN_DESC
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds * File:
121da177e4SLinus Torvalds * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * Purpose:
151da177e4SLinus Torvalds * Floating-point to Unsigned Fixed-point Converts with Truncation
161da177e4SLinus Torvalds *
171da177e4SLinus Torvalds * External Interfaces:
181da177e4SLinus Torvalds * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
191da177e4SLinus Torvalds * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
201da177e4SLinus Torvalds * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
211da177e4SLinus Torvalds * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
221da177e4SLinus Torvalds *
231da177e4SLinus Torvalds * Internal Interfaces:
241da177e4SLinus Torvalds *
251da177e4SLinus Torvalds * Theory:
261da177e4SLinus Torvalds * <<please update with a overview of the operation of this file>>
271da177e4SLinus Torvalds *
281da177e4SLinus Torvalds * END_DESC
291da177e4SLinus Torvalds */
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds #include "float.h"
331da177e4SLinus Torvalds #include "sgl_float.h"
341da177e4SLinus Torvalds #include "dbl_float.h"
351da177e4SLinus Torvalds #include "cnv_float.h"
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds /************************************************************************
381da177e4SLinus Torvalds * Floating-point to Unsigned Fixed-point Converts with Truncation *
391da177e4SLinus Torvalds ************************************************************************/
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds /*
421da177e4SLinus Torvalds * Convert single floating-point to single fixed-point format
431da177e4SLinus Torvalds * with truncated result
441da177e4SLinus Torvalds */
451da177e4SLinus Torvalds /*ARGSUSED*/
461da177e4SLinus Torvalds int
sgl_to_sgl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)471da177e4SLinus Torvalds sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
481da177e4SLinus Torvalds unsigned int *dstptr, unsigned int *status)
491da177e4SLinus Torvalds {
501da177e4SLinus Torvalds register unsigned int src, result;
511da177e4SLinus Torvalds register int src_exponent;
521da177e4SLinus Torvalds
531da177e4SLinus Torvalds src = *srcptr;
541da177e4SLinus Torvalds src_exponent = Sgl_exponent(src) - SGL_BIAS;
551da177e4SLinus Torvalds
561da177e4SLinus Torvalds /*
571da177e4SLinus Torvalds * Test for overflow
581da177e4SLinus Torvalds */
591da177e4SLinus Torvalds if (src_exponent > SGL_FX_MAX_EXP + 1) {
601da177e4SLinus Torvalds if (Sgl_isone_sign(src)) {
611da177e4SLinus Torvalds result = 0;
621da177e4SLinus Torvalds } else {
631da177e4SLinus Torvalds result = 0xffffffff;
641da177e4SLinus Torvalds }
651da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
661da177e4SLinus Torvalds return(INVALIDEXCEPTION);
671da177e4SLinus Torvalds }
681da177e4SLinus Torvalds Set_invalidflag();
691da177e4SLinus Torvalds *dstptr = result;
701da177e4SLinus Torvalds return(NOEXCEPTION);
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds /*
731da177e4SLinus Torvalds * Generate result
741da177e4SLinus Torvalds */
751da177e4SLinus Torvalds if (src_exponent >= 0) {
761da177e4SLinus Torvalds /*
771da177e4SLinus Torvalds * Check sign.
781da177e4SLinus Torvalds * If negative, trap unimplemented.
791da177e4SLinus Torvalds */
801da177e4SLinus Torvalds if (Sgl_isone_sign(src)) {
811da177e4SLinus Torvalds result = 0;
821da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
831da177e4SLinus Torvalds return(INVALIDEXCEPTION);
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds Set_invalidflag();
861da177e4SLinus Torvalds *dstptr = result;
871da177e4SLinus Torvalds return(NOEXCEPTION);
881da177e4SLinus Torvalds }
891da177e4SLinus Torvalds Sgl_clear_signexponent_set_hidden(src);
901da177e4SLinus Torvalds Suint_from_sgl_mantissa(src,src_exponent,result);
911da177e4SLinus Torvalds *dstptr = result;
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds /* check for inexact */
941da177e4SLinus Torvalds if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
951da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
961da177e4SLinus Torvalds else Set_inexactflag();
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds else {
1001da177e4SLinus Torvalds *dstptr = 0;
1011da177e4SLinus Torvalds
1021da177e4SLinus Torvalds /* check for inexact */
1031da177e4SLinus Torvalds if (Sgl_isnotzero_exponentmantissa(src)) {
1041da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1051da177e4SLinus Torvalds else Set_inexactflag();
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds return(NOEXCEPTION);
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds
1111da177e4SLinus Torvalds /*
1121da177e4SLinus Torvalds * Single Floating-point to Double Unsigned Fixed
1131da177e4SLinus Torvalds */
1141da177e4SLinus Torvalds /*ARGSUSED*/
1151da177e4SLinus Torvalds int
sgl_to_dbl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)1161da177e4SLinus Torvalds sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
1171da177e4SLinus Torvalds dbl_unsigned * dstptr, unsigned int *status)
1181da177e4SLinus Torvalds {
1191da177e4SLinus Torvalds register int src_exponent;
1201da177e4SLinus Torvalds register unsigned int src, resultp1, resultp2;
1211da177e4SLinus Torvalds
1221da177e4SLinus Torvalds src = *srcptr;
1231da177e4SLinus Torvalds src_exponent = Sgl_exponent(src) - SGL_BIAS;
1241da177e4SLinus Torvalds
1251da177e4SLinus Torvalds /*
1261da177e4SLinus Torvalds * Test for overflow
1271da177e4SLinus Torvalds */
1281da177e4SLinus Torvalds if (src_exponent > DBL_FX_MAX_EXP + 1) {
1291da177e4SLinus Torvalds if (Sgl_isone_sign(src)) {
1301da177e4SLinus Torvalds resultp1 = resultp2 = 0;
1311da177e4SLinus Torvalds } else {
1321da177e4SLinus Torvalds resultp1 = resultp2 = 0xffffffff;
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
1351da177e4SLinus Torvalds return(INVALIDEXCEPTION);
1361da177e4SLinus Torvalds }
1371da177e4SLinus Torvalds Set_invalidflag();
1381da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
1391da177e4SLinus Torvalds return(NOEXCEPTION);
1401da177e4SLinus Torvalds }
1411da177e4SLinus Torvalds /*
1421da177e4SLinus Torvalds * Generate result
1431da177e4SLinus Torvalds */
1441da177e4SLinus Torvalds if (src_exponent >= 0) {
1451da177e4SLinus Torvalds /*
1461da177e4SLinus Torvalds * Check sign.
1471da177e4SLinus Torvalds * If negative, trap unimplemented.
1481da177e4SLinus Torvalds */
1491da177e4SLinus Torvalds if (Sgl_isone_sign(src)) {
1501da177e4SLinus Torvalds resultp1 = resultp2 = 0;
1511da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
1521da177e4SLinus Torvalds return(INVALIDEXCEPTION);
1531da177e4SLinus Torvalds }
1541da177e4SLinus Torvalds Set_invalidflag();
1551da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
1561da177e4SLinus Torvalds return(NOEXCEPTION);
1571da177e4SLinus Torvalds }
1581da177e4SLinus Torvalds Sgl_clear_signexponent_set_hidden(src);
1591da177e4SLinus Torvalds Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
1601da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
1611da177e4SLinus Torvalds
1621da177e4SLinus Torvalds /* check for inexact */
1631da177e4SLinus Torvalds if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
1641da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1651da177e4SLinus Torvalds else Set_inexactflag();
1661da177e4SLinus Torvalds }
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds else {
1691da177e4SLinus Torvalds Duint_setzero(resultp1,resultp2);
1701da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds /* check for inexact */
1731da177e4SLinus Torvalds if (Sgl_isnotzero_exponentmantissa(src)) {
1741da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1751da177e4SLinus Torvalds else Set_inexactflag();
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds return(NOEXCEPTION);
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvalds /*
1821da177e4SLinus Torvalds * Double Floating-point to Single Unsigned Fixed
1831da177e4SLinus Torvalds */
1841da177e4SLinus Torvalds /*ARGSUSED*/
1851da177e4SLinus Torvalds int
dbl_to_sgl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)1861da177e4SLinus Torvalds dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
1871da177e4SLinus Torvalds unsigned int *dstptr, unsigned int *status)
1881da177e4SLinus Torvalds {
1891da177e4SLinus Torvalds register unsigned int srcp1, srcp2, result;
1901da177e4SLinus Torvalds register int src_exponent;
1911da177e4SLinus Torvalds
1921da177e4SLinus Torvalds Dbl_copyfromptr(srcptr,srcp1,srcp2);
1931da177e4SLinus Torvalds src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
1941da177e4SLinus Torvalds
1951da177e4SLinus Torvalds /*
1961da177e4SLinus Torvalds * Test for overflow
1971da177e4SLinus Torvalds */
1981da177e4SLinus Torvalds if (src_exponent > SGL_FX_MAX_EXP + 1) {
1991da177e4SLinus Torvalds if (Dbl_isone_sign(srcp1)) {
2001da177e4SLinus Torvalds result = 0;
2011da177e4SLinus Torvalds } else {
2021da177e4SLinus Torvalds result = 0xffffffff;
2031da177e4SLinus Torvalds }
2041da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
2051da177e4SLinus Torvalds return(INVALIDEXCEPTION);
2061da177e4SLinus Torvalds }
2071da177e4SLinus Torvalds Set_invalidflag();
2081da177e4SLinus Torvalds *dstptr = result;
2091da177e4SLinus Torvalds return(NOEXCEPTION);
2101da177e4SLinus Torvalds }
2111da177e4SLinus Torvalds /*
2121da177e4SLinus Torvalds * Generate result
2131da177e4SLinus Torvalds */
2141da177e4SLinus Torvalds if (src_exponent >= 0) {
2151da177e4SLinus Torvalds /*
2161da177e4SLinus Torvalds * Check sign.
2171da177e4SLinus Torvalds * If negative, trap unimplemented.
2181da177e4SLinus Torvalds */
2191da177e4SLinus Torvalds if (Dbl_isone_sign(srcp1)) {
2201da177e4SLinus Torvalds result = 0;
2211da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
2221da177e4SLinus Torvalds return(INVALIDEXCEPTION);
2231da177e4SLinus Torvalds }
2241da177e4SLinus Torvalds Set_invalidflag();
2251da177e4SLinus Torvalds *dstptr = result;
2261da177e4SLinus Torvalds return(NOEXCEPTION);
2271da177e4SLinus Torvalds }
2281da177e4SLinus Torvalds Dbl_clear_signexponent_set_hidden(srcp1);
2291da177e4SLinus Torvalds Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
2301da177e4SLinus Torvalds *dstptr = result;
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds /* check for inexact */
2331da177e4SLinus Torvalds if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
2341da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
2351da177e4SLinus Torvalds else Set_inexactflag();
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds else {
2391da177e4SLinus Torvalds *dstptr = 0;
2401da177e4SLinus Torvalds
2411da177e4SLinus Torvalds /* check for inexact */
2421da177e4SLinus Torvalds if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
2431da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
2441da177e4SLinus Torvalds else Set_inexactflag();
2451da177e4SLinus Torvalds }
2461da177e4SLinus Torvalds }
2471da177e4SLinus Torvalds return(NOEXCEPTION);
2481da177e4SLinus Torvalds }
2491da177e4SLinus Torvalds
2501da177e4SLinus Torvalds /*
2511da177e4SLinus Torvalds * Double Floating-point to Double Unsigned Fixed
2521da177e4SLinus Torvalds */
2531da177e4SLinus Torvalds /*ARGSUSED*/
2541da177e4SLinus Torvalds int
dbl_to_dbl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)2551da177e4SLinus Torvalds dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
2561da177e4SLinus Torvalds dbl_unsigned * dstptr, unsigned int *status)
2571da177e4SLinus Torvalds {
2581da177e4SLinus Torvalds register int src_exponent;
2591da177e4SLinus Torvalds register unsigned int srcp1, srcp2, resultp1, resultp2;
2601da177e4SLinus Torvalds
2611da177e4SLinus Torvalds Dbl_copyfromptr(srcptr,srcp1,srcp2);
2621da177e4SLinus Torvalds src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
2631da177e4SLinus Torvalds
2641da177e4SLinus Torvalds /*
2651da177e4SLinus Torvalds * Test for overflow
2661da177e4SLinus Torvalds */
2671da177e4SLinus Torvalds if (src_exponent > DBL_FX_MAX_EXP + 1) {
2681da177e4SLinus Torvalds if (Dbl_isone_sign(srcp1)) {
2691da177e4SLinus Torvalds resultp1 = resultp2 = 0;
2701da177e4SLinus Torvalds } else {
2711da177e4SLinus Torvalds resultp1 = resultp2 = 0xffffffff;
2721da177e4SLinus Torvalds }
2731da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
2741da177e4SLinus Torvalds return(INVALIDEXCEPTION);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds Set_invalidflag();
2771da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
2781da177e4SLinus Torvalds return(NOEXCEPTION);
2791da177e4SLinus Torvalds }
2801da177e4SLinus Torvalds /*
2811da177e4SLinus Torvalds * Generate result
2821da177e4SLinus Torvalds */
2831da177e4SLinus Torvalds if (src_exponent >= 0) {
2841da177e4SLinus Torvalds /*
2851da177e4SLinus Torvalds * Check sign.
2861da177e4SLinus Torvalds * If negative, trap unimplemented.
2871da177e4SLinus Torvalds */
2881da177e4SLinus Torvalds if (Dbl_isone_sign(srcp1)) {
2891da177e4SLinus Torvalds resultp1 = resultp2 = 0;
2901da177e4SLinus Torvalds if (Is_invalidtrap_enabled()) {
2911da177e4SLinus Torvalds return(INVALIDEXCEPTION);
2921da177e4SLinus Torvalds }
2931da177e4SLinus Torvalds Set_invalidflag();
2941da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
2951da177e4SLinus Torvalds return(NOEXCEPTION);
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds Dbl_clear_signexponent_set_hidden(srcp1);
2981da177e4SLinus Torvalds Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
2991da177e4SLinus Torvalds resultp1,resultp2);
3001da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
3011da177e4SLinus Torvalds
3021da177e4SLinus Torvalds /* check for inexact */
3031da177e4SLinus Torvalds if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
3041da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
3051da177e4SLinus Torvalds else Set_inexactflag();
3061da177e4SLinus Torvalds }
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds else {
3091da177e4SLinus Torvalds Duint_setzero(resultp1,resultp2);
3101da177e4SLinus Torvalds Duint_copytoptr(resultp1,resultp2,dstptr);
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds /* check for inexact */
3131da177e4SLinus Torvalds if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
3141da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
3151da177e4SLinus Torvalds else Set_inexactflag();
3161da177e4SLinus Torvalds }
3171da177e4SLinus Torvalds }
3181da177e4SLinus Torvalds return(NOEXCEPTION);
3191da177e4SLinus Torvalds }
320