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 * Purpose: 128c2ecf20Sopenharmony_ci * Single Floating-point Round to Integer 138c2ecf20Sopenharmony_ci * Double Floating-point Round to Integer 148c2ecf20Sopenharmony_ci * Quad Floating-point Round to Integer (returns unimplemented) 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * External Interfaces: 178c2ecf20Sopenharmony_ci * dbl_frnd(srcptr,nullptr,dstptr,status) 188c2ecf20Sopenharmony_ci * sgl_frnd(srcptr,nullptr,dstptr,status) 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * END_DESC 218c2ecf20Sopenharmony_ci*/ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "float.h" 258c2ecf20Sopenharmony_ci#include "sgl_float.h" 268c2ecf20Sopenharmony_ci#include "dbl_float.h" 278c2ecf20Sopenharmony_ci#include "cnv_float.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Single Floating-point Round to Integer 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/*ARGSUSED*/ 348c2ecf20Sopenharmony_ciint 358c2ecf20Sopenharmony_cisgl_frnd(sgl_floating_point *srcptr, 368c2ecf20Sopenharmony_ci unsigned int *nullptr, 378c2ecf20Sopenharmony_ci sgl_floating_point *dstptr, 388c2ecf20Sopenharmony_ci unsigned int *status) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci register unsigned int src, result; 418c2ecf20Sopenharmony_ci register int src_exponent; 428c2ecf20Sopenharmony_ci register boolean inexact = FALSE; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci src = *srcptr; 458c2ecf20Sopenharmony_ci /* 468c2ecf20Sopenharmony_ci * check source operand for NaN or infinity 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 498c2ecf20Sopenharmony_ci /* 508c2ecf20Sopenharmony_ci * is signaling NaN? 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(src)) { 538c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 548c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 558c2ecf20Sopenharmony_ci /* make NaN quiet */ 568c2ecf20Sopenharmony_ci Set_invalidflag(); 578c2ecf20Sopenharmony_ci Sgl_set_quiet(src); 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci /* 608c2ecf20Sopenharmony_ci * return quiet NaN or infinity 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci *dstptr = src; 638c2ecf20Sopenharmony_ci return(NOEXCEPTION); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci /* 668c2ecf20Sopenharmony_ci * Need to round? 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { 698c2ecf20Sopenharmony_ci *dstptr = src; 708c2ecf20Sopenharmony_ci return(NOEXCEPTION); 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Generate result 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci if (src_exponent >= 0) { 768c2ecf20Sopenharmony_ci Sgl_clear_exponent_set_hidden(src); 778c2ecf20Sopenharmony_ci result = src; 788c2ecf20Sopenharmony_ci Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); 798c2ecf20Sopenharmony_ci /* check for inexact */ 808c2ecf20Sopenharmony_ci if (Sgl_isinexact_to_fix(src,src_exponent)) { 818c2ecf20Sopenharmony_ci inexact = TRUE; 828c2ecf20Sopenharmony_ci /* round result */ 838c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 848c2ecf20Sopenharmony_ci case ROUNDPLUS: 858c2ecf20Sopenharmony_ci if (Sgl_iszero_sign(src)) Sgl_increment(result); 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci case ROUNDMINUS: 888c2ecf20Sopenharmony_ci if (Sgl_isone_sign(src)) Sgl_increment(result); 898c2ecf20Sopenharmony_ci break; 908c2ecf20Sopenharmony_ci case ROUNDNEAREST: 918c2ecf20Sopenharmony_ci if (Sgl_isone_roundbit(src,src_exponent)) 928c2ecf20Sopenharmony_ci if (Sgl_isone_stickybit(src,src_exponent) 938c2ecf20Sopenharmony_ci || (Sgl_isone_lowmantissa(result))) 948c2ecf20Sopenharmony_ci Sgl_increment(result); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); 988c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(result)) 998c2ecf20Sopenharmony_ci Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); 1008c2ecf20Sopenharmony_ci else Sgl_set_exponent(result,src_exponent + SGL_BIAS); 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci else { 1038c2ecf20Sopenharmony_ci result = src; /* set sign */ 1048c2ecf20Sopenharmony_ci Sgl_setzero_exponentmantissa(result); 1058c2ecf20Sopenharmony_ci /* check for inexact */ 1068c2ecf20Sopenharmony_ci if (Sgl_isnotzero_exponentmantissa(src)) { 1078c2ecf20Sopenharmony_ci inexact = TRUE; 1088c2ecf20Sopenharmony_ci /* round result */ 1098c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 1108c2ecf20Sopenharmony_ci case ROUNDPLUS: 1118c2ecf20Sopenharmony_ci if (Sgl_iszero_sign(src)) 1128c2ecf20Sopenharmony_ci Sgl_set_exponent(result,SGL_BIAS); 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case ROUNDMINUS: 1158c2ecf20Sopenharmony_ci if (Sgl_isone_sign(src)) 1168c2ecf20Sopenharmony_ci Sgl_set_exponent(result,SGL_BIAS); 1178c2ecf20Sopenharmony_ci break; 1188c2ecf20Sopenharmony_ci case ROUNDNEAREST: 1198c2ecf20Sopenharmony_ci if (src_exponent == -1) 1208c2ecf20Sopenharmony_ci if (Sgl_isnotzero_mantissa(src)) 1218c2ecf20Sopenharmony_ci Sgl_set_exponent(result,SGL_BIAS); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci *dstptr = result; 1268c2ecf20Sopenharmony_ci if (inexact) { 1278c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 1288c2ecf20Sopenharmony_ci else Set_inexactflag(); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * Double Floating-point Round to Integer 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/*ARGSUSED*/ 1388c2ecf20Sopenharmony_ciint 1398c2ecf20Sopenharmony_cidbl_frnd( 1408c2ecf20Sopenharmony_ci dbl_floating_point *srcptr, 1418c2ecf20Sopenharmony_ci unsigned int *nullptr, 1428c2ecf20Sopenharmony_ci dbl_floating_point *dstptr, 1438c2ecf20Sopenharmony_ci unsigned int *status) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci register unsigned int srcp1, srcp2, resultp1, resultp2; 1468c2ecf20Sopenharmony_ci register int src_exponent; 1478c2ecf20Sopenharmony_ci register boolean inexact = FALSE; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci Dbl_copyfromptr(srcptr,srcp1,srcp2); 1508c2ecf20Sopenharmony_ci /* 1518c2ecf20Sopenharmony_ci * check source operand for NaN or infinity 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { 1548c2ecf20Sopenharmony_ci /* 1558c2ecf20Sopenharmony_ci * is signaling NaN? 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(srcp1)) { 1588c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 1598c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 1608c2ecf20Sopenharmony_ci /* make NaN quiet */ 1618c2ecf20Sopenharmony_ci Set_invalidflag(); 1628c2ecf20Sopenharmony_ci Dbl_set_quiet(srcp1); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * return quiet NaN or infinity 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci Dbl_copytoptr(srcp1,srcp2,dstptr); 1688c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci /* 1718c2ecf20Sopenharmony_ci * Need to round? 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { 1748c2ecf20Sopenharmony_ci Dbl_copytoptr(srcp1,srcp2,dstptr); 1758c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci /* 1788c2ecf20Sopenharmony_ci * Generate result 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci if (src_exponent >= 0) { 1818c2ecf20Sopenharmony_ci Dbl_clear_exponent_set_hidden(srcp1); 1828c2ecf20Sopenharmony_ci resultp1 = srcp1; 1838c2ecf20Sopenharmony_ci resultp2 = srcp2; 1848c2ecf20Sopenharmony_ci Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 1858c2ecf20Sopenharmony_ci /* check for inexact */ 1868c2ecf20Sopenharmony_ci if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 1878c2ecf20Sopenharmony_ci inexact = TRUE; 1888c2ecf20Sopenharmony_ci /* round result */ 1898c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 1908c2ecf20Sopenharmony_ci case ROUNDPLUS: 1918c2ecf20Sopenharmony_ci if (Dbl_iszero_sign(srcp1)) 1928c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci case ROUNDMINUS: 1958c2ecf20Sopenharmony_ci if (Dbl_isone_sign(srcp1)) 1968c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci case ROUNDNEAREST: 1998c2ecf20Sopenharmony_ci if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 2008c2ecf20Sopenharmony_ci if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 2018c2ecf20Sopenharmony_ci || (Dbl_isone_lowmantissap2(resultp2))) 2028c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 2068c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) 2078c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); 2088c2ecf20Sopenharmony_ci else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci else { 2118c2ecf20Sopenharmony_ci resultp1 = srcp1; /* set sign */ 2128c2ecf20Sopenharmony_ci Dbl_setzero_exponentmantissa(resultp1,resultp2); 2138c2ecf20Sopenharmony_ci /* check for inexact */ 2148c2ecf20Sopenharmony_ci if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 2158c2ecf20Sopenharmony_ci inexact = TRUE; 2168c2ecf20Sopenharmony_ci /* round result */ 2178c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 2188c2ecf20Sopenharmony_ci case ROUNDPLUS: 2198c2ecf20Sopenharmony_ci if (Dbl_iszero_sign(srcp1)) 2208c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1,DBL_BIAS); 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci case ROUNDMINUS: 2238c2ecf20Sopenharmony_ci if (Dbl_isone_sign(srcp1)) 2248c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1,DBL_BIAS); 2258c2ecf20Sopenharmony_ci break; 2268c2ecf20Sopenharmony_ci case ROUNDNEAREST: 2278c2ecf20Sopenharmony_ci if (src_exponent == -1) 2288c2ecf20Sopenharmony_ci if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 2298c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1,DBL_BIAS); 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 2348c2ecf20Sopenharmony_ci if (inexact) { 2358c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 2368c2ecf20Sopenharmony_ci else Set_inexactflag(); 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci return(NOEXCEPTION); 2398c2ecf20Sopenharmony_ci} 240