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/fcnvuf.c $Revision: 1.1 $ 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * Purpose: 151da177e4SLinus Torvalds * Fixed point to Floating-point Converts 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * External Interfaces: 181da177e4SLinus Torvalds * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 191da177e4SLinus Torvalds * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 201da177e4SLinus Torvalds * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 211da177e4SLinus Torvalds * sgl_to_sgl_fcnvuf(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 * Fixed point to Floating-point Converts * 391da177e4SLinus Torvalds ************************************************************************/ 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds /* 421da177e4SLinus Torvalds * Convert Single Unsigned Fixed to Single Floating-point format 431da177e4SLinus Torvalds */ 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds int 461da177e4SLinus Torvalds sgl_to_sgl_fcnvuf( 471da177e4SLinus Torvalds unsigned int *srcptr, 481da177e4SLinus Torvalds unsigned int *nullptr, 491da177e4SLinus Torvalds sgl_floating_point *dstptr, 501da177e4SLinus Torvalds unsigned int *status) 511da177e4SLinus Torvalds { 521da177e4SLinus Torvalds register unsigned int src, result = 0; 531da177e4SLinus Torvalds register int dst_exponent; 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds src = *srcptr; 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds /* Check for zero */ 581da177e4SLinus Torvalds if (src == 0) { 591da177e4SLinus Torvalds Sgl_setzero(result); 601da177e4SLinus Torvalds *dstptr = result; 611da177e4SLinus Torvalds return(NOEXCEPTION); 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds /* 641da177e4SLinus Torvalds * Generate exponent and normalized mantissa 651da177e4SLinus Torvalds */ 661da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 671da177e4SLinus Torvalds /* 681da177e4SLinus Torvalds * Check word for most significant bit set. Returns 691da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 701da177e4SLinus Torvalds * between -1 and 30. 711da177e4SLinus Torvalds */ 721da177e4SLinus Torvalds Find_ms_one_bit(src,dst_exponent); 731da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 741da177e4SLinus Torvalds src <<= dst_exponent+1; 751da177e4SLinus Torvalds Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); 761da177e4SLinus Torvalds Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds /* check for inexact */ 791da177e4SLinus Torvalds if (Suint_isinexact_to_sgl(src)) { 801da177e4SLinus Torvalds switch (Rounding_mode()) { 811da177e4SLinus Torvalds case ROUNDPLUS: 821da177e4SLinus Torvalds Sgl_increment(result); 831da177e4SLinus Torvalds break; 841da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 851da177e4SLinus Torvalds break; 861da177e4SLinus Torvalds case ROUNDNEAREST: 871da177e4SLinus Torvalds Sgl_roundnearest_from_suint(src,result); 881da177e4SLinus Torvalds break; 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 911da177e4SLinus Torvalds *dstptr = result; 921da177e4SLinus Torvalds return(INEXACTEXCEPTION); 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds else Set_inexactflag(); 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds *dstptr = result; 971da177e4SLinus Torvalds return(NOEXCEPTION); 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds /* 1011da177e4SLinus Torvalds * Single Unsigned Fixed to Double Floating-point 1021da177e4SLinus Torvalds */ 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds int 1051da177e4SLinus Torvalds sgl_to_dbl_fcnvuf( 1061da177e4SLinus Torvalds unsigned int *srcptr, 1071da177e4SLinus Torvalds unsigned int *nullptr, 1081da177e4SLinus Torvalds dbl_floating_point *dstptr, 1091da177e4SLinus Torvalds unsigned int *status) 1101da177e4SLinus Torvalds { 1111da177e4SLinus Torvalds register int dst_exponent; 1121da177e4SLinus Torvalds register unsigned int src, resultp1 = 0, resultp2 = 0; 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds src = *srcptr; 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* Check for zero */ 1171da177e4SLinus Torvalds if (src == 0) { 1181da177e4SLinus Torvalds Dbl_setzero(resultp1,resultp2); 1191da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 1201da177e4SLinus Torvalds return(NOEXCEPTION); 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds /* 1231da177e4SLinus Torvalds * Generate exponent and normalized mantissa 1241da177e4SLinus Torvalds */ 1251da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 1261da177e4SLinus Torvalds /* 1271da177e4SLinus Torvalds * Check word for most significant bit set. Returns 1281da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 1291da177e4SLinus Torvalds * between -1 and 30. 1301da177e4SLinus Torvalds */ 1311da177e4SLinus Torvalds Find_ms_one_bit(src,dst_exponent); 1321da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 1331da177e4SLinus Torvalds src <<= dst_exponent+1; 1341da177e4SLinus Torvalds Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); 1351da177e4SLinus Torvalds Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); 1361da177e4SLinus Torvalds Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 1371da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 1381da177e4SLinus Torvalds return(NOEXCEPTION); 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds /* 1421da177e4SLinus Torvalds * Double Unsigned Fixed to Single Floating-point 1431da177e4SLinus Torvalds */ 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds int 1461da177e4SLinus Torvalds dbl_to_sgl_fcnvuf( 1471da177e4SLinus Torvalds dbl_unsigned *srcptr, 1481da177e4SLinus Torvalds unsigned int *nullptr, 1491da177e4SLinus Torvalds sgl_floating_point *dstptr, 1501da177e4SLinus Torvalds unsigned int *status) 1511da177e4SLinus Torvalds { 1521da177e4SLinus Torvalds int dst_exponent; 1531da177e4SLinus Torvalds unsigned int srcp1, srcp2, result = 0; 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds Duint_copyfromptr(srcptr,srcp1,srcp2); 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* Check for zero */ 1581da177e4SLinus Torvalds if (srcp1 == 0 && srcp2 == 0) { 1591da177e4SLinus Torvalds Sgl_setzero(result); 1601da177e4SLinus Torvalds *dstptr = result; 1611da177e4SLinus Torvalds return(NOEXCEPTION); 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds /* 1641da177e4SLinus Torvalds * Generate exponent and normalized mantissa 1651da177e4SLinus Torvalds */ 1661da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 1671da177e4SLinus Torvalds if (srcp1 == 0) { 1681da177e4SLinus Torvalds /* 1691da177e4SLinus Torvalds * Check word for most significant bit set. Returns 1701da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 1711da177e4SLinus Torvalds * between -1 and 30. 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds Find_ms_one_bit(srcp2,dst_exponent); 1741da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 1751da177e4SLinus Torvalds srcp1 = srcp2 << dst_exponent+1; 1761da177e4SLinus Torvalds srcp2 = 0; 1771da177e4SLinus Torvalds /* 1781da177e4SLinus Torvalds * since msb set is in second word, need to 1791da177e4SLinus Torvalds * adjust bit position count 1801da177e4SLinus Torvalds */ 1811da177e4SLinus Torvalds dst_exponent += 32; 1821da177e4SLinus Torvalds } 1831da177e4SLinus Torvalds else { 1841da177e4SLinus Torvalds /* 1851da177e4SLinus Torvalds * Check word for most significant bit set. Returns 1861da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 1871da177e4SLinus Torvalds * between -1 and 30. 1881da177e4SLinus Torvalds * 1891da177e4SLinus Torvalds */ 1901da177e4SLinus Torvalds Find_ms_one_bit(srcp1,dst_exponent); 1911da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 1921da177e4SLinus Torvalds if (dst_exponent >= 0) { 1931da177e4SLinus Torvalds Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 1941da177e4SLinus Torvalds srcp1); 1951da177e4SLinus Torvalds srcp2 <<= dst_exponent+1; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); 1991da177e4SLinus Torvalds Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds /* check for inexact */ 2021da177e4SLinus Torvalds if (Duint_isinexact_to_sgl(srcp1,srcp2)) { 2031da177e4SLinus Torvalds switch (Rounding_mode()) { 2041da177e4SLinus Torvalds case ROUNDPLUS: 2051da177e4SLinus Torvalds Sgl_increment(result); 2061da177e4SLinus Torvalds break; 2071da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 2081da177e4SLinus Torvalds break; 2091da177e4SLinus Torvalds case ROUNDNEAREST: 2101da177e4SLinus Torvalds Sgl_roundnearest_from_duint(srcp1,srcp2,result); 2111da177e4SLinus Torvalds break; 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 2141da177e4SLinus Torvalds *dstptr = result; 2151da177e4SLinus Torvalds return(INEXACTEXCEPTION); 2161da177e4SLinus Torvalds } 2171da177e4SLinus Torvalds else Set_inexactflag(); 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds *dstptr = result; 2201da177e4SLinus Torvalds return(NOEXCEPTION); 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds /* 2241da177e4SLinus Torvalds * Double Unsigned Fixed to Double Floating-point 2251da177e4SLinus Torvalds */ 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds int 2281da177e4SLinus Torvalds dbl_to_dbl_fcnvuf( 2291da177e4SLinus Torvalds dbl_unsigned *srcptr, 2301da177e4SLinus Torvalds unsigned int *nullptr, 2311da177e4SLinus Torvalds dbl_floating_point *dstptr, 2321da177e4SLinus Torvalds unsigned int *status) 2331da177e4SLinus Torvalds { 2341da177e4SLinus Torvalds register int dst_exponent; 2351da177e4SLinus Torvalds register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds Duint_copyfromptr(srcptr,srcp1,srcp2); 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds /* Check for zero */ 2401da177e4SLinus Torvalds if (srcp1 == 0 && srcp2 ==0) { 2411da177e4SLinus Torvalds Dbl_setzero(resultp1,resultp2); 2421da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 2431da177e4SLinus Torvalds return(NOEXCEPTION); 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds /* 2461da177e4SLinus Torvalds * Generate exponent and normalized mantissa 2471da177e4SLinus Torvalds */ 2481da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 2491da177e4SLinus Torvalds if (srcp1 == 0) { 2501da177e4SLinus Torvalds /* 2511da177e4SLinus Torvalds * Check word for most significant bit set. Returns 2521da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 2531da177e4SLinus Torvalds * between -1 and 30. 2541da177e4SLinus Torvalds */ 2551da177e4SLinus Torvalds Find_ms_one_bit(srcp2,dst_exponent); 2561da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 2571da177e4SLinus Torvalds srcp1 = srcp2 << dst_exponent+1; 2581da177e4SLinus Torvalds srcp2 = 0; 2591da177e4SLinus Torvalds /* 2601da177e4SLinus Torvalds * since msb set is in second word, need to 2611da177e4SLinus Torvalds * adjust bit position count 2621da177e4SLinus Torvalds */ 2631da177e4SLinus Torvalds dst_exponent += 32; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds else { 2661da177e4SLinus Torvalds /* 2671da177e4SLinus Torvalds * Check word for most significant bit set. Returns 2681da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 2691da177e4SLinus Torvalds * between -1 and 30. 2701da177e4SLinus Torvalds */ 2711da177e4SLinus Torvalds Find_ms_one_bit(srcp1,dst_exponent); 2721da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 2731da177e4SLinus Torvalds if (dst_exponent >= 0) { 2741da177e4SLinus Torvalds Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 2751da177e4SLinus Torvalds srcp1); 2761da177e4SLinus Torvalds srcp2 <<= dst_exponent+1; 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); 2801da177e4SLinus Torvalds Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); 2811da177e4SLinus Torvalds Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* check for inexact */ 2841da177e4SLinus Torvalds if (Duint_isinexact_to_dbl(srcp2)) { 2851da177e4SLinus Torvalds switch (Rounding_mode()) { 2861da177e4SLinus Torvalds case ROUNDPLUS: 2871da177e4SLinus Torvalds Dbl_increment(resultp1,resultp2); 2881da177e4SLinus Torvalds break; 2891da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 2901da177e4SLinus Torvalds break; 2911da177e4SLinus Torvalds case ROUNDNEAREST: 2921da177e4SLinus Torvalds Dbl_roundnearest_from_duint(srcp2,resultp1, 2931da177e4SLinus Torvalds resultp2); 2941da177e4SLinus Torvalds break; 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 2971da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 2981da177e4SLinus Torvalds return(INEXACTEXCEPTION); 2991da177e4SLinus Torvalds } 3001da177e4SLinus Torvalds else Set_inexactflag(); 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 3031da177e4SLinus Torvalds return(NOEXCEPTION); 3041da177e4SLinus Torvalds } 3051da177e4SLinus Torvalds 306