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 * File: 25 * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $ 26 * 27 * Purpose: 28 * Single Floating-point to Double Floating-point 29 * Double Floating-point to Single Floating-point 30 * 31 * External Interfaces: 32 * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) 33 * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) 34 * 35 * Internal Interfaces: 36 * 37 * Theory: 38 * <<please update with a overview of the operation of this file>> 39 * 40 * END_DESC 41 */ 42 43 44 #include "float.h" 45 #include "sgl_float.h" 46 #include "dbl_float.h" 47 #include "cnv_float.h" 48 49 /* 50 * Single Floating-point to Double Floating-point 51 */ 52 /*ARGSUSED*/ 53 int 54 sgl_to_dbl_fcnvff( 55 sgl_floating_point *srcptr, 56 unsigned int *nullptr, 57 dbl_floating_point *dstptr, 58 unsigned int *status) 59 { 60 register unsigned int src, resultp1, resultp2; 61 register int src_exponent; 62 63 src = *srcptr; 64 src_exponent = Sgl_exponent(src); 65 Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ 66 /* 67 * Test for NaN or infinity 68 */ 69 if (src_exponent == SGL_INFINITY_EXPONENT) { 70 /* 71 * determine if NaN or infinity 72 */ 73 if (Sgl_iszero_mantissa(src)) { 74 /* 75 * is infinity; want to return double infinity 76 */ 77 Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 78 Dbl_copytoptr(resultp1,resultp2,dstptr); 79 return(NOEXCEPTION); 80 } 81 else { 82 /* 83 * is NaN; signaling or quiet? 84 */ 85 if (Sgl_isone_signaling(src)) { 86 /* trap if INVALIDTRAP enabled */ 87 if (Is_invalidtrap_enabled()) 88 return(INVALIDEXCEPTION); 89 /* make NaN quiet */ 90 else { 91 Set_invalidflag(); 92 Sgl_set_quiet(src); 93 } 94 } 95 /* 96 * NaN is quiet, return as double NaN 97 */ 98 Dbl_setinfinity_exponent(resultp1); 99 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 100 Dbl_copytoptr(resultp1,resultp2,dstptr); 101 return(NOEXCEPTION); 102 } 103 } 104 /* 105 * Test for zero or denormalized 106 */ 107 if (src_exponent == 0) { 108 /* 109 * determine if zero or denormalized 110 */ 111 if (Sgl_isnotzero_mantissa(src)) { 112 /* 113 * is denormalized; want to normalize 114 */ 115 Sgl_clear_signexponent(src); 116 Sgl_leftshiftby1(src); 117 Sgl_normalize(src,src_exponent); 118 Sgl_to_dbl_exponent(src_exponent,resultp1); 119 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 120 } 121 else { 122 Dbl_setzero_exponentmantissa(resultp1,resultp2); 123 } 124 Dbl_copytoptr(resultp1,resultp2,dstptr); 125 return(NOEXCEPTION); 126 } 127 /* 128 * No special cases, just complete the conversion 129 */ 130 Sgl_to_dbl_exponent(src_exponent, resultp1); 131 Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); 132 Dbl_copytoptr(resultp1,resultp2,dstptr); 133 return(NOEXCEPTION); 134 } 135 136 /* 137 * Double Floating-point to Single Floating-point 138 */ 139 /*ARGSUSED*/ 140 int 141 dbl_to_sgl_fcnvff( 142 dbl_floating_point *srcptr, 143 unsigned int *nullptr, 144 sgl_floating_point *dstptr, 145 unsigned int *status) 146 { 147 register unsigned int srcp1, srcp2, result; 148 register int src_exponent, dest_exponent, dest_mantissa; 149 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; 150 register boolean lsb_odd = FALSE; 151 boolean is_tiny = FALSE; 152 153 Dbl_copyfromptr(srcptr,srcp1,srcp2); 154 src_exponent = Dbl_exponent(srcp1); 155 Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ 156 /* 157 * Test for NaN or infinity 158 */ 159 if (src_exponent == DBL_INFINITY_EXPONENT) { 160 /* 161 * determine if NaN or infinity 162 */ 163 if (Dbl_iszero_mantissa(srcp1,srcp2)) { 164 /* 165 * is infinity; want to return single infinity 166 */ 167 Sgl_setinfinity_exponentmantissa(result); 168 *dstptr = result; 169 return(NOEXCEPTION); 170 } 171 /* 172 * is NaN; signaling or quiet? 173 */ 174 if (Dbl_isone_signaling(srcp1)) { 175 /* trap if INVALIDTRAP enabled */ 176 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 177 else { 178 Set_invalidflag(); 179 /* make NaN quiet */ 180 Dbl_set_quiet(srcp1); 181 } 182 } 183 /* 184 * NaN is quiet, return as single NaN 185 */ 186 Sgl_setinfinity_exponent(result); 187 Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); 188 if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); 189 *dstptr = result; 190 return(NOEXCEPTION); 191 } 192 /* 193 * Generate result 194 */ 195 Dbl_to_sgl_exponent(src_exponent,dest_exponent); 196 if (dest_exponent > 0) { 197 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, 198 stickybit,lsb_odd); 199 } 200 else { 201 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ 202 Sgl_setzero_exponentmantissa(result); 203 *dstptr = result; 204 return(NOEXCEPTION); 205 } 206 if (Is_underflowtrap_enabled()) { 207 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, 208 guardbit,stickybit,lsb_odd); 209 } 210 else { 211 /* compute result, determine inexact info, 212 * and set Underflowflag if appropriate 213 */ 214 Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, 215 dest_mantissa,inexact,guardbit,stickybit,lsb_odd, 216 is_tiny); 217 } 218 } 219 /* 220 * Now round result if not exact 221 */ 222 if (inexact) { 223 switch (Rounding_mode()) { 224 case ROUNDPLUS: 225 if (Sgl_iszero_sign(result)) dest_mantissa++; 226 break; 227 case ROUNDMINUS: 228 if (Sgl_isone_sign(result)) dest_mantissa++; 229 break; 230 case ROUNDNEAREST: 231 if (guardbit) { 232 if (stickybit || lsb_odd) dest_mantissa++; 233 } 234 } 235 } 236 Sgl_set_exponentmantissa(result,dest_mantissa); 237 238 /* 239 * check for mantissa overflow after rounding 240 */ 241 if ((dest_exponent>0 || Is_underflowtrap_enabled()) && 242 Sgl_isone_hidden(result)) dest_exponent++; 243 244 /* 245 * Test for overflow 246 */ 247 if (dest_exponent >= SGL_INFINITY_EXPONENT) { 248 /* trap if OVERFLOWTRAP enabled */ 249 if (Is_overflowtrap_enabled()) { 250 /* 251 * Check for gross overflow 252 */ 253 if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) 254 return(UNIMPLEMENTEDEXCEPTION); 255 256 /* 257 * Adjust bias of result 258 */ 259 Sgl_setwrapped_exponent(result,dest_exponent,ovfl); 260 *dstptr = result; 261 if (inexact) 262 if (Is_inexacttrap_enabled()) 263 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); 264 else Set_inexactflag(); 265 return(OVERFLOWEXCEPTION); 266 } 267 Set_overflowflag(); 268 inexact = TRUE; 269 /* set result to infinity or largest number */ 270 Sgl_setoverflow(result); 271 } 272 /* 273 * Test for underflow 274 */ 275 else if (dest_exponent <= 0) { 276 /* trap if UNDERFLOWTRAP enabled */ 277 if (Is_underflowtrap_enabled()) { 278 /* 279 * Check for gross underflow 280 */ 281 if (dest_exponent <= -(SGL_WRAP)) 282 return(UNIMPLEMENTEDEXCEPTION); 283 /* 284 * Adjust bias of result 285 */ 286 Sgl_setwrapped_exponent(result,dest_exponent,unfl); 287 *dstptr = result; 288 if (inexact) 289 if (Is_inexacttrap_enabled()) 290 return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); 291 else Set_inexactflag(); 292 return(UNDERFLOWEXCEPTION); 293 } 294 /* 295 * result is denormalized or signed zero 296 */ 297 if (inexact && is_tiny) Set_underflowflag(); 298 299 } 300 else Sgl_set_exponent(result,dest_exponent); 301 *dstptr = result; 302 /* 303 * Trap if inexact trap is enabled 304 */ 305 if (inexact) 306 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 307 else Set_inexactflag(); 308 return(NOEXCEPTION); 309 } 310