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