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