1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 4 * 5 * Floating-point emulation code 6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 7 */ 8 /* 9 * BEGIN_DESC 10 * 11 * Purpose: 12 * Single Floating-point Round to Integer 13 * Double Floating-point Round to Integer 14 * Quad Floating-point Round to Integer (returns unimplemented) 15 * 16 * External Interfaces: 17 * dbl_frnd(srcptr,_nullptr,dstptr,status) 18 * sgl_frnd(srcptr,_nullptr,dstptr,status) 19 * 20 * END_DESC 21 */ 22 23 24 #include "float.h" 25 #include "sgl_float.h" 26 #include "dbl_float.h" 27 #include "cnv_float.h" 28 29 /* 30 * Single Floating-point Round to Integer 31 */ 32 33 /*ARGSUSED*/ 34 int 35 sgl_frnd(sgl_floating_point *srcptr, 36 unsigned int *_nullptr, 37 sgl_floating_point *dstptr, 38 unsigned int *status) 39 { 40 register unsigned int src, result; 41 register int src_exponent; 42 register boolean inexact = FALSE; 43 44 src = *srcptr; 45 /* 46 * check source operand for NaN or infinity 47 */ 48 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 49 /* 50 * is signaling NaN? 51 */ 52 if (Sgl_isone_signaling(src)) { 53 /* trap if INVALIDTRAP enabled */ 54 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 55 /* make NaN quiet */ 56 Set_invalidflag(); 57 Sgl_set_quiet(src); 58 } 59 /* 60 * return quiet NaN or infinity 61 */ 62 *dstptr = src; 63 return(NOEXCEPTION); 64 } 65 /* 66 * Need to round? 67 */ 68 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { 69 *dstptr = src; 70 return(NOEXCEPTION); 71 } 72 /* 73 * Generate result 74 */ 75 if (src_exponent >= 0) { 76 Sgl_clear_exponent_set_hidden(src); 77 result = src; 78 Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); 79 /* check for inexact */ 80 if (Sgl_isinexact_to_fix(src,src_exponent)) { 81 inexact = TRUE; 82 /* round result */ 83 switch (Rounding_mode()) { 84 case ROUNDPLUS: 85 if (Sgl_iszero_sign(src)) Sgl_increment(result); 86 break; 87 case ROUNDMINUS: 88 if (Sgl_isone_sign(src)) Sgl_increment(result); 89 break; 90 case ROUNDNEAREST: 91 if (Sgl_isone_roundbit(src,src_exponent)) 92 if (Sgl_isone_stickybit(src,src_exponent) 93 || (Sgl_isone_lowmantissa(result))) 94 Sgl_increment(result); 95 } 96 } 97 Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); 98 if (Sgl_isone_hiddenoverflow(result)) 99 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); 100 else Sgl_set_exponent(result,src_exponent + SGL_BIAS); 101 } 102 else { 103 result = src; /* set sign */ 104 Sgl_setzero_exponentmantissa(result); 105 /* check for inexact */ 106 if (Sgl_isnotzero_exponentmantissa(src)) { 107 inexact = TRUE; 108 /* round result */ 109 switch (Rounding_mode()) { 110 case ROUNDPLUS: 111 if (Sgl_iszero_sign(src)) 112 Sgl_set_exponent(result,SGL_BIAS); 113 break; 114 case ROUNDMINUS: 115 if (Sgl_isone_sign(src)) 116 Sgl_set_exponent(result,SGL_BIAS); 117 break; 118 case ROUNDNEAREST: 119 if (src_exponent == -1) 120 if (Sgl_isnotzero_mantissa(src)) 121 Sgl_set_exponent(result,SGL_BIAS); 122 } 123 } 124 } 125 *dstptr = result; 126 if (inexact) { 127 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 128 else Set_inexactflag(); 129 } 130 return(NOEXCEPTION); 131 } 132 133 /* 134 * Double Floating-point Round to Integer 135 */ 136 137 /*ARGSUSED*/ 138 int 139 dbl_frnd( 140 dbl_floating_point *srcptr, 141 unsigned int *_nullptr, 142 dbl_floating_point *dstptr, 143 unsigned int *status) 144 { 145 register unsigned int srcp1, srcp2, resultp1, resultp2; 146 register int src_exponent; 147 register boolean inexact = FALSE; 148 149 Dbl_copyfromptr(srcptr,srcp1,srcp2); 150 /* 151 * check source operand for NaN or infinity 152 */ 153 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { 154 /* 155 * is signaling NaN? 156 */ 157 if (Dbl_isone_signaling(srcp1)) { 158 /* trap if INVALIDTRAP enabled */ 159 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 160 /* make NaN quiet */ 161 Set_invalidflag(); 162 Dbl_set_quiet(srcp1); 163 } 164 /* 165 * return quiet NaN or infinity 166 */ 167 Dbl_copytoptr(srcp1,srcp2,dstptr); 168 return(NOEXCEPTION); 169 } 170 /* 171 * Need to round? 172 */ 173 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { 174 Dbl_copytoptr(srcp1,srcp2,dstptr); 175 return(NOEXCEPTION); 176 } 177 /* 178 * Generate result 179 */ 180 if (src_exponent >= 0) { 181 Dbl_clear_exponent_set_hidden(srcp1); 182 resultp1 = srcp1; 183 resultp2 = srcp2; 184 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 185 /* check for inexact */ 186 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 187 inexact = TRUE; 188 /* round result */ 189 switch (Rounding_mode()) { 190 case ROUNDPLUS: 191 if (Dbl_iszero_sign(srcp1)) 192 Dbl_increment(resultp1,resultp2); 193 break; 194 case ROUNDMINUS: 195 if (Dbl_isone_sign(srcp1)) 196 Dbl_increment(resultp1,resultp2); 197 break; 198 case ROUNDNEAREST: 199 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 200 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 201 || (Dbl_isone_lowmantissap2(resultp2))) 202 Dbl_increment(resultp1,resultp2); 203 } 204 } 205 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 206 if (Dbl_isone_hiddenoverflow(resultp1)) 207 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); 208 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); 209 } 210 else { 211 resultp1 = srcp1; /* set sign */ 212 Dbl_setzero_exponentmantissa(resultp1,resultp2); 213 /* check for inexact */ 214 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 215 inexact = TRUE; 216 /* round result */ 217 switch (Rounding_mode()) { 218 case ROUNDPLUS: 219 if (Dbl_iszero_sign(srcp1)) 220 Dbl_set_exponent(resultp1,DBL_BIAS); 221 break; 222 case ROUNDMINUS: 223 if (Dbl_isone_sign(srcp1)) 224 Dbl_set_exponent(resultp1,DBL_BIAS); 225 break; 226 case ROUNDNEAREST: 227 if (src_exponent == -1) 228 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 229 Dbl_set_exponent(resultp1,DBL_BIAS); 230 } 231 } 232 } 233 Dbl_copytoptr(resultp1,resultp2,dstptr); 234 if (inexact) { 235 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 236 else Set_inexactflag(); 237 } 238 return(NOEXCEPTION); 239 } 240