18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Floating-point emulation code 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * BEGIN_DESC 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * File: 128c2ecf20Sopenharmony_ci * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $ 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Purpose: 158c2ecf20Sopenharmony_ci * Fixed point to Floating-point Converts 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * External Interfaces: 188c2ecf20Sopenharmony_ci * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 198c2ecf20Sopenharmony_ci * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 208c2ecf20Sopenharmony_ci * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 218c2ecf20Sopenharmony_ci * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Internal Interfaces: 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Theory: 268c2ecf20Sopenharmony_ci * <<please update with a overview of the operation of this file>> 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * END_DESC 298c2ecf20Sopenharmony_ci*/ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "float.h" 338c2ecf20Sopenharmony_ci#include "sgl_float.h" 348c2ecf20Sopenharmony_ci#include "dbl_float.h" 358c2ecf20Sopenharmony_ci#include "cnv_float.h" 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/************************************************************************ 388c2ecf20Sopenharmony_ci * Fixed point to Floating-point Converts * 398c2ecf20Sopenharmony_ci ************************************************************************/ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * Convert Single Unsigned Fixed to Single Floating-point format 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciint 468c2ecf20Sopenharmony_cisgl_to_sgl_fcnvuf( 478c2ecf20Sopenharmony_ci unsigned int *srcptr, 488c2ecf20Sopenharmony_ci unsigned int *nullptr, 498c2ecf20Sopenharmony_ci sgl_floating_point *dstptr, 508c2ecf20Sopenharmony_ci unsigned int *status) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci register unsigned int src, result = 0; 538c2ecf20Sopenharmony_ci register int dst_exponent; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci src = *srcptr; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* Check for zero */ 588c2ecf20Sopenharmony_ci if (src == 0) { 598c2ecf20Sopenharmony_ci Sgl_setzero(result); 608c2ecf20Sopenharmony_ci *dstptr = result; 618c2ecf20Sopenharmony_ci return(NOEXCEPTION); 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci /* 648c2ecf20Sopenharmony_ci * Generate exponent and normalized mantissa 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 678c2ecf20Sopenharmony_ci /* 688c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 698c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 708c2ecf20Sopenharmony_ci * between -1 and 30. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci Find_ms_one_bit(src,dst_exponent); 738c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 748c2ecf20Sopenharmony_ci src <<= dst_exponent+1; 758c2ecf20Sopenharmony_ci Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); 768c2ecf20Sopenharmony_ci Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* check for inexact */ 798c2ecf20Sopenharmony_ci if (Suint_isinexact_to_sgl(src)) { 808c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 818c2ecf20Sopenharmony_ci case ROUNDPLUS: 828c2ecf20Sopenharmony_ci Sgl_increment(result); 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case ROUNDMINUS: /* never negative */ 858c2ecf20Sopenharmony_ci break; 868c2ecf20Sopenharmony_ci case ROUNDNEAREST: 878c2ecf20Sopenharmony_ci Sgl_roundnearest_from_suint(src,result); 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) { 918c2ecf20Sopenharmony_ci *dstptr = result; 928c2ecf20Sopenharmony_ci return(INEXACTEXCEPTION); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci else Set_inexactflag(); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci *dstptr = result; 978c2ecf20Sopenharmony_ci return(NOEXCEPTION); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * Single Unsigned Fixed to Double Floating-point 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciint 1058c2ecf20Sopenharmony_cisgl_to_dbl_fcnvuf( 1068c2ecf20Sopenharmony_ci unsigned int *srcptr, 1078c2ecf20Sopenharmony_ci unsigned int *nullptr, 1088c2ecf20Sopenharmony_ci dbl_floating_point *dstptr, 1098c2ecf20Sopenharmony_ci unsigned int *status) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci register int dst_exponent; 1128c2ecf20Sopenharmony_ci register unsigned int src, resultp1 = 0, resultp2 = 0; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci src = *srcptr; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* Check for zero */ 1178c2ecf20Sopenharmony_ci if (src == 0) { 1188c2ecf20Sopenharmony_ci Dbl_setzero(resultp1,resultp2); 1198c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1208c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci /* 1238c2ecf20Sopenharmony_ci * Generate exponent and normalized mantissa 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 1288c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 1298c2ecf20Sopenharmony_ci * between -1 and 30. 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci Find_ms_one_bit(src,dst_exponent); 1328c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 1338c2ecf20Sopenharmony_ci src <<= dst_exponent+1; 1348c2ecf20Sopenharmony_ci Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); 1358c2ecf20Sopenharmony_ci Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); 1368c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 1378c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1388c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* 1428c2ecf20Sopenharmony_ci * Double Unsigned Fixed to Single Floating-point 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ciint 1468c2ecf20Sopenharmony_cidbl_to_sgl_fcnvuf( 1478c2ecf20Sopenharmony_ci dbl_unsigned *srcptr, 1488c2ecf20Sopenharmony_ci unsigned int *nullptr, 1498c2ecf20Sopenharmony_ci sgl_floating_point *dstptr, 1508c2ecf20Sopenharmony_ci unsigned int *status) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci int dst_exponent; 1538c2ecf20Sopenharmony_ci unsigned int srcp1, srcp2, result = 0; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci Duint_copyfromptr(srcptr,srcp1,srcp2); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Check for zero */ 1588c2ecf20Sopenharmony_ci if (srcp1 == 0 && srcp2 == 0) { 1598c2ecf20Sopenharmony_ci Sgl_setzero(result); 1608c2ecf20Sopenharmony_ci *dstptr = result; 1618c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci /* 1648c2ecf20Sopenharmony_ci * Generate exponent and normalized mantissa 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 1678c2ecf20Sopenharmony_ci if (srcp1 == 0) { 1688c2ecf20Sopenharmony_ci /* 1698c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 1708c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 1718c2ecf20Sopenharmony_ci * between -1 and 30. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci Find_ms_one_bit(srcp2,dst_exponent); 1748c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 1758c2ecf20Sopenharmony_ci srcp1 = srcp2 << dst_exponent+1; 1768c2ecf20Sopenharmony_ci srcp2 = 0; 1778c2ecf20Sopenharmony_ci /* 1788c2ecf20Sopenharmony_ci * since msb set is in second word, need to 1798c2ecf20Sopenharmony_ci * adjust bit position count 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci dst_exponent += 32; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci else { 1848c2ecf20Sopenharmony_ci /* 1858c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 1868c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 1878c2ecf20Sopenharmony_ci * between -1 and 30. 1888c2ecf20Sopenharmony_ci * 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci Find_ms_one_bit(srcp1,dst_exponent); 1918c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 1928c2ecf20Sopenharmony_ci if (dst_exponent >= 0) { 1938c2ecf20Sopenharmony_ci Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 1948c2ecf20Sopenharmony_ci srcp1); 1958c2ecf20Sopenharmony_ci srcp2 <<= dst_exponent+1; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); 1998c2ecf20Sopenharmony_ci Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* check for inexact */ 2028c2ecf20Sopenharmony_ci if (Duint_isinexact_to_sgl(srcp1,srcp2)) { 2038c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 2048c2ecf20Sopenharmony_ci case ROUNDPLUS: 2058c2ecf20Sopenharmony_ci Sgl_increment(result); 2068c2ecf20Sopenharmony_ci break; 2078c2ecf20Sopenharmony_ci case ROUNDMINUS: /* never negative */ 2088c2ecf20Sopenharmony_ci break; 2098c2ecf20Sopenharmony_ci case ROUNDNEAREST: 2108c2ecf20Sopenharmony_ci Sgl_roundnearest_from_duint(srcp1,srcp2,result); 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) { 2148c2ecf20Sopenharmony_ci *dstptr = result; 2158c2ecf20Sopenharmony_ci return(INEXACTEXCEPTION); 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci else Set_inexactflag(); 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci *dstptr = result; 2208c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* 2248c2ecf20Sopenharmony_ci * Double Unsigned Fixed to Double Floating-point 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciint 2288c2ecf20Sopenharmony_cidbl_to_dbl_fcnvuf( 2298c2ecf20Sopenharmony_ci dbl_unsigned *srcptr, 2308c2ecf20Sopenharmony_ci unsigned int *nullptr, 2318c2ecf20Sopenharmony_ci dbl_floating_point *dstptr, 2328c2ecf20Sopenharmony_ci unsigned int *status) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci register int dst_exponent; 2358c2ecf20Sopenharmony_ci register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci Duint_copyfromptr(srcptr,srcp1,srcp2); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Check for zero */ 2408c2ecf20Sopenharmony_ci if (srcp1 == 0 && srcp2 ==0) { 2418c2ecf20Sopenharmony_ci Dbl_setzero(resultp1,resultp2); 2428c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 2438c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci /* 2468c2ecf20Sopenharmony_ci * Generate exponent and normalized mantissa 2478c2ecf20Sopenharmony_ci */ 2488c2ecf20Sopenharmony_ci dst_exponent = 16; /* initialize for normalization */ 2498c2ecf20Sopenharmony_ci if (srcp1 == 0) { 2508c2ecf20Sopenharmony_ci /* 2518c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 2528c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 2538c2ecf20Sopenharmony_ci * between -1 and 30. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_ci Find_ms_one_bit(srcp2,dst_exponent); 2568c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 2578c2ecf20Sopenharmony_ci srcp1 = srcp2 << dst_exponent+1; 2588c2ecf20Sopenharmony_ci srcp2 = 0; 2598c2ecf20Sopenharmony_ci /* 2608c2ecf20Sopenharmony_ci * since msb set is in second word, need to 2618c2ecf20Sopenharmony_ci * adjust bit position count 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci dst_exponent += 32; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci else { 2668c2ecf20Sopenharmony_ci /* 2678c2ecf20Sopenharmony_ci * Check word for most significant bit set. Returns 2688c2ecf20Sopenharmony_ci * a value in dst_exponent indicating the bit position, 2698c2ecf20Sopenharmony_ci * between -1 and 30. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci Find_ms_one_bit(srcp1,dst_exponent); 2728c2ecf20Sopenharmony_ci /* left justify source, with msb at bit position 0 */ 2738c2ecf20Sopenharmony_ci if (dst_exponent >= 0) { 2748c2ecf20Sopenharmony_ci Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 2758c2ecf20Sopenharmony_ci srcp1); 2768c2ecf20Sopenharmony_ci srcp2 <<= dst_exponent+1; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); 2808c2ecf20Sopenharmony_ci Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); 2818c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* check for inexact */ 2848c2ecf20Sopenharmony_ci if (Duint_isinexact_to_dbl(srcp2)) { 2858c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 2868c2ecf20Sopenharmony_ci case ROUNDPLUS: 2878c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 2888c2ecf20Sopenharmony_ci break; 2898c2ecf20Sopenharmony_ci case ROUNDMINUS: /* never negative */ 2908c2ecf20Sopenharmony_ci break; 2918c2ecf20Sopenharmony_ci case ROUNDNEAREST: 2928c2ecf20Sopenharmony_ci Dbl_roundnearest_from_duint(srcp2,resultp1, 2938c2ecf20Sopenharmony_ci resultp2); 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) { 2978c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 2988c2ecf20Sopenharmony_ci return(INEXACTEXCEPTION); 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci else Set_inexactflag(); 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 3038c2ecf20Sopenharmony_ci return(NOEXCEPTION); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 306