1 1.4 skrll /* $NetBSD: fcnvxf.c,v 1.4 2012/02/04 17:03:10 skrll Exp $ */ 2 1.1 fredette 3 1.1 fredette /* $OpenBSD: fcnvxf.c,v 1.5 2001/03/29 03:58:18 mickey Exp $ */ 4 1.1 fredette 5 1.1 fredette /* 6 1.1 fredette * Copyright 1996 1995 by Open Software Foundation, Inc. 7 1.1 fredette * All Rights Reserved 8 1.1 fredette * 9 1.1 fredette * Permission to use, copy, modify, and distribute this software and 10 1.1 fredette * its documentation for any purpose and without fee is hereby granted, 11 1.1 fredette * provided that the above copyright notice appears in all copies and 12 1.1 fredette * that both the copyright notice and this permission notice appear in 13 1.1 fredette * supporting documentation. 14 1.1 fredette * 15 1.1 fredette * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 16 1.1 fredette * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 17 1.1 fredette * FOR A PARTICULAR PURPOSE. 18 1.1 fredette * 19 1.1 fredette * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 20 1.1 fredette * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 21 1.1 fredette * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 22 1.1 fredette * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 23 1.1 fredette * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 1.1 fredette * 25 1.1 fredette */ 26 1.1 fredette /* 27 1.1 fredette * pmk1.1 28 1.1 fredette */ 29 1.1 fredette /* 30 1.1 fredette * (c) Copyright 1986 HEWLETT-PACKARD COMPANY 31 1.1 fredette * 32 1.1 fredette * To anyone who acknowledges that this file is provided "AS IS" 33 1.1 fredette * without any express or implied warranty: 34 1.1 fredette * permission to use, copy, modify, and distribute this file 35 1.1 fredette * for any purpose is hereby granted without fee, provided that 36 1.1 fredette * the above copyright notice and this notice appears in all 37 1.1 fredette * copies, and that the name of Hewlett-Packard Company not be 38 1.1 fredette * used in advertising or publicity pertaining to distribution 39 1.1 fredette * of the software without specific, written prior permission. 40 1.1 fredette * Hewlett-Packard Company makes no representations about the 41 1.1 fredette * suitability of this software for any purpose. 42 1.1 fredette */ 43 1.2 lukem 44 1.2 lukem #include <sys/cdefs.h> 45 1.4 skrll __KERNEL_RCSID(0, "$NetBSD: fcnvxf.c,v 1.4 2012/02/04 17:03:10 skrll Exp $"); 46 1.1 fredette 47 1.1 fredette #include "../spmath/float.h" 48 1.1 fredette #include "../spmath/sgl_float.h" 49 1.1 fredette #include "../spmath/dbl_float.h" 50 1.1 fredette #include "../spmath/cnv_float.h" 51 1.1 fredette 52 1.1 fredette /* 53 1.1 fredette * Convert single fixed-point to single floating-point format 54 1.1 fredette */ 55 1.1 fredette int 56 1.4 skrll sgl_to_sgl_fcnvxf(int *srcptr, sgl_floating_point *dstptr, 57 1.4 skrll unsigned int *status) 58 1.1 fredette { 59 1.1 fredette register int src, dst_exponent; 60 1.1 fredette register unsigned int result = 0; 61 1.1 fredette 62 1.1 fredette src = *srcptr; 63 1.1 fredette /* 64 1.1 fredette * set sign bit of result and get magnitude of source 65 1.1 fredette */ 66 1.1 fredette if (src < 0) { 67 1.1 fredette Sgl_setone_sign(result); 68 1.1 fredette Int_negate(src); 69 1.1 fredette } 70 1.1 fredette else { 71 1.1 fredette Sgl_setzero_sign(result); 72 1.1 fredette /* Check for zero */ 73 1.1 fredette if (src == 0) { 74 1.1 fredette Sgl_setzero(result); 75 1.1 fredette *dstptr = result; 76 1.1 fredette return(NOEXCEPTION); 77 1.1 fredette } 78 1.1 fredette } 79 1.1 fredette /* 80 1.1 fredette * Generate exponent and normalized mantissa 81 1.1 fredette */ 82 1.1 fredette dst_exponent = 16; /* initialize for normalization */ 83 1.1 fredette /* 84 1.1 fredette * Check word for most significant bit set. Returns 85 1.1 fredette * a value in dst_exponent indicating the bit position, 86 1.1 fredette * between -1 and 30. 87 1.1 fredette */ 88 1.1 fredette Find_ms_one_bit(src,dst_exponent); 89 1.1 fredette /* left justify source, with msb at bit position 1 */ 90 1.1 fredette if (dst_exponent >= 0) src <<= dst_exponent; 91 1.1 fredette else src = 1 << 30; 92 1.1 fredette Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); 93 1.1 fredette Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 94 1.1 fredette 95 1.1 fredette /* check for inexact */ 96 1.1 fredette if (Int_isinexact_to_sgl(src)) { 97 1.1 fredette switch (Rounding_mode()) { 98 1.1 fredette case ROUNDPLUS: 99 1.1 fredette if (Sgl_iszero_sign(result)) 100 1.1 fredette Sgl_increment(result); 101 1.1 fredette break; 102 1.1 fredette case ROUNDMINUS: 103 1.1 fredette if (Sgl_isone_sign(result)) 104 1.1 fredette Sgl_increment(result); 105 1.1 fredette break; 106 1.1 fredette case ROUNDNEAREST: 107 1.1 fredette Sgl_roundnearest_from_int(src,result); 108 1.1 fredette } 109 1.1 fredette if (Is_inexacttrap_enabled()) { 110 1.1 fredette *dstptr = result; 111 1.1 fredette return(INEXACTEXCEPTION); 112 1.1 fredette } 113 1.1 fredette else Set_inexactflag(); 114 1.1 fredette } 115 1.1 fredette *dstptr = result; 116 1.1 fredette return(NOEXCEPTION); 117 1.1 fredette } 118 1.1 fredette 119 1.1 fredette /* 120 1.1 fredette * Single Fixed-point to Double Floating-point 121 1.1 fredette */ 122 1.1 fredette int 123 1.4 skrll sgl_to_dbl_fcnvxf(int *srcptr, dbl_floating_point *dstptr, 124 1.4 skrll unsigned int *status) 125 1.1 fredette { 126 1.1 fredette register int src, dst_exponent; 127 1.1 fredette register unsigned int resultp1 = 0, resultp2 = 0; 128 1.1 fredette 129 1.1 fredette src = *srcptr; 130 1.1 fredette /* 131 1.1 fredette * set sign bit of result and get magnitude of source 132 1.1 fredette */ 133 1.1 fredette if (src < 0) { 134 1.1 fredette Dbl_setone_sign(resultp1); 135 1.1 fredette Int_negate(src); 136 1.1 fredette } 137 1.1 fredette else { 138 1.1 fredette Dbl_setzero_sign(resultp1); 139 1.1 fredette /* Check for zero */ 140 1.1 fredette if (src == 0) { 141 1.1 fredette Dbl_setzero(resultp1,resultp2); 142 1.1 fredette Dbl_copytoptr(resultp1,resultp2,dstptr); 143 1.1 fredette return(NOEXCEPTION); 144 1.1 fredette } 145 1.1 fredette } 146 1.1 fredette /* 147 1.1 fredette * Generate exponent and normalized mantissa 148 1.1 fredette */ 149 1.1 fredette dst_exponent = 16; /* initialize for normalization */ 150 1.1 fredette /* 151 1.1 fredette * Check word for most significant bit set. Returns 152 1.1 fredette * a value in dst_exponent indicating the bit position, 153 1.1 fredette * between -1 and 30. 154 1.1 fredette */ 155 1.1 fredette Find_ms_one_bit(src,dst_exponent); 156 1.1 fredette /* left justify source, with msb at bit position 1 */ 157 1.1 fredette if (dst_exponent >= 0) src <<= dst_exponent; 158 1.1 fredette else src = 1 << 30; 159 1.1 fredette Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1))); 160 1.1 fredette Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH))); 161 1.1 fredette Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 162 1.1 fredette Dbl_copytoptr(resultp1,resultp2,dstptr); 163 1.1 fredette return(NOEXCEPTION); 164 1.1 fredette } 165 1.1 fredette 166 1.1 fredette /* 167 1.1 fredette * Double Fixed-point to Single Floating-point 168 1.1 fredette */ 169 1.1 fredette int 170 1.4 skrll dbl_to_sgl_fcnvxf(dbl_integer *srcptr, sgl_floating_point *dstptr, 171 1.4 skrll unsigned int *status) 172 1.1 fredette { 173 1.1 fredette int dst_exponent, srcp1; 174 1.1 fredette unsigned int result = 0, srcp2; 175 1.1 fredette 176 1.1 fredette Dint_copyfromptr(srcptr,srcp1,srcp2); 177 1.1 fredette /* 178 1.1 fredette * set sign bit of result and get magnitude of source 179 1.1 fredette */ 180 1.1 fredette if (srcp1 < 0) { 181 1.1 fredette Sgl_setone_sign(result); 182 1.1 fredette Dint_negate(srcp1,srcp2); 183 1.1 fredette } 184 1.1 fredette else { 185 1.1 fredette Sgl_setzero_sign(result); 186 1.1 fredette /* Check for zero */ 187 1.1 fredette if (srcp1 == 0 && srcp2 == 0) { 188 1.1 fredette Sgl_setzero(result); 189 1.1 fredette *dstptr = result; 190 1.1 fredette return(NOEXCEPTION); 191 1.1 fredette } 192 1.1 fredette } 193 1.1 fredette /* 194 1.1 fredette * Generate exponent and normalized mantissa 195 1.1 fredette */ 196 1.1 fredette dst_exponent = 16; /* initialize for normalization */ 197 1.1 fredette if (srcp1 == 0) { 198 1.1 fredette /* 199 1.1 fredette * Check word for most significant bit set. Returns 200 1.1 fredette * a value in dst_exponent indicating the bit position, 201 1.1 fredette * between -1 and 30. 202 1.1 fredette */ 203 1.1 fredette Find_ms_one_bit(srcp2,dst_exponent); 204 1.1 fredette /* left justify source, with msb at bit position 1 */ 205 1.1 fredette if (dst_exponent >= 0) { 206 1.1 fredette srcp1 = srcp2 << dst_exponent; 207 1.1 fredette srcp2 = 0; 208 1.1 fredette } 209 1.1 fredette else { 210 1.1 fredette srcp1 = srcp2 >> 1; 211 1.1 fredette srcp2 <<= 31; 212 1.1 fredette } 213 1.1 fredette /* 214 1.1 fredette * since msb set is in second word, need to 215 1.1 fredette * adjust bit position count 216 1.1 fredette */ 217 1.1 fredette dst_exponent += 32; 218 1.1 fredette } 219 1.1 fredette else { 220 1.1 fredette /* 221 1.1 fredette * Check word for most significant bit set. Returns 222 1.1 fredette * a value in dst_exponent indicating the bit position, 223 1.1 fredette * between -1 and 30. 224 1.1 fredette * 225 1.1 fredette */ 226 1.1 fredette Find_ms_one_bit(srcp1,dst_exponent); 227 1.1 fredette /* left justify source, with msb at bit position 1 */ 228 1.1 fredette if (dst_exponent > 0) { 229 1.1 fredette Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 230 1.1 fredette srcp1); 231 1.1 fredette srcp2 <<= dst_exponent; 232 1.1 fredette } 233 1.1 fredette /* 234 1.1 fredette * If dst_exponent = 0, we don't need to shift anything. 235 1.1 fredette * If dst_exponent = -1, src = - 2**63 so we won't need to 236 1.1 fredette * shift srcp2. 237 1.1 fredette */ 238 1.1 fredette else srcp1 >>= -(dst_exponent); 239 1.1 fredette } 240 1.1 fredette Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1))); 241 1.1 fredette Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 242 1.1 fredette 243 1.1 fredette /* check for inexact */ 244 1.1 fredette if (Dint_isinexact_to_sgl(srcp1,srcp2)) { 245 1.1 fredette switch (Rounding_mode()) { 246 1.1 fredette case ROUNDPLUS: 247 1.1 fredette if (Sgl_iszero_sign(result)) 248 1.1 fredette Sgl_increment(result); 249 1.1 fredette break; 250 1.1 fredette case ROUNDMINUS: 251 1.1 fredette if (Sgl_isone_sign(result)) 252 1.1 fredette Sgl_increment(result); 253 1.1 fredette break; 254 1.1 fredette case ROUNDNEAREST: 255 1.1 fredette Sgl_roundnearest_from_dint(srcp1,srcp2,result); 256 1.1 fredette } 257 1.1 fredette if (Is_inexacttrap_enabled()) { 258 1.1 fredette *dstptr = result; 259 1.1 fredette return(INEXACTEXCEPTION); 260 1.1 fredette } 261 1.1 fredette else Set_inexactflag(); 262 1.1 fredette } 263 1.1 fredette *dstptr = result; 264 1.1 fredette return(NOEXCEPTION); 265 1.1 fredette } 266 1.1 fredette 267 1.1 fredette /* 268 1.1 fredette * Double Fixed-point to Double Floating-point 269 1.1 fredette */ 270 1.1 fredette int 271 1.4 skrll dbl_to_dbl_fcnvxf(dbl_integer *srcptr, dbl_floating_point *dstptr, 272 1.4 skrll unsigned int *status) 273 1.1 fredette { 274 1.1 fredette register int srcp1, dst_exponent; 275 1.1 fredette register unsigned int srcp2, resultp1 = 0, resultp2 = 0; 276 1.1 fredette 277 1.1 fredette Dint_copyfromptr(srcptr,srcp1,srcp2); 278 1.1 fredette /* 279 1.1 fredette * set sign bit of result and get magnitude of source 280 1.1 fredette */ 281 1.1 fredette if (srcp1 < 0) { 282 1.1 fredette Dbl_setone_sign(resultp1); 283 1.1 fredette Dint_negate(srcp1,srcp2); 284 1.1 fredette } 285 1.1 fredette else { 286 1.1 fredette Dbl_setzero_sign(resultp1); 287 1.1 fredette /* Check for zero */ 288 1.1 fredette if (srcp1 == 0 && srcp2 ==0) { 289 1.1 fredette Dbl_setzero(resultp1,resultp2); 290 1.1 fredette Dbl_copytoptr(resultp1,resultp2,dstptr); 291 1.1 fredette return(NOEXCEPTION); 292 1.1 fredette } 293 1.1 fredette } 294 1.1 fredette /* 295 1.1 fredette * Generate exponent and normalized mantissa 296 1.1 fredette */ 297 1.1 fredette dst_exponent = 16; /* initialize for normalization */ 298 1.1 fredette if (srcp1 == 0) { 299 1.1 fredette /* 300 1.1 fredette * Check word for most significant bit set. Returns 301 1.1 fredette * a value in dst_exponent indicating the bit position, 302 1.1 fredette * between -1 and 30. 303 1.1 fredette */ 304 1.1 fredette Find_ms_one_bit(srcp2,dst_exponent); 305 1.1 fredette /* left justify source, with msb at bit position 1 */ 306 1.1 fredette if (dst_exponent >= 0) { 307 1.1 fredette srcp1 = srcp2 << dst_exponent; 308 1.1 fredette srcp2 = 0; 309 1.1 fredette } 310 1.1 fredette else { 311 1.1 fredette srcp1 = srcp2 >> 1; 312 1.1 fredette srcp2 <<= 31; 313 1.1 fredette } 314 1.1 fredette /* 315 1.1 fredette * since msb set is in second word, need to 316 1.1 fredette * adjust bit position count 317 1.1 fredette */ 318 1.1 fredette dst_exponent += 32; 319 1.1 fredette } 320 1.1 fredette else { 321 1.1 fredette /* 322 1.1 fredette * Check word for most significant bit set. Returns 323 1.1 fredette * a value in dst_exponent indicating the bit position, 324 1.1 fredette * between -1 and 30. 325 1.1 fredette */ 326 1.1 fredette Find_ms_one_bit(srcp1,dst_exponent); 327 1.1 fredette /* left justify source, with msb at bit position 1 */ 328 1.1 fredette if (dst_exponent > 0) { 329 1.1 fredette Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 330 1.1 fredette srcp1); 331 1.1 fredette srcp2 <<= dst_exponent; 332 1.1 fredette } 333 1.1 fredette /* 334 1.1 fredette * If dst_exponent = 0, we don't need to shift anything. 335 1.1 fredette * If dst_exponent = -1, src = - 2**63 so we won't need to 336 1.1 fredette * shift srcp2. 337 1.1 fredette */ 338 1.1 fredette else srcp1 >>= -(dst_exponent); 339 1.1 fredette } 340 1.1 fredette Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); 341 1.1 fredette Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); 342 1.1 fredette Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 343 1.1 fredette 344 1.1 fredette /* check for inexact */ 345 1.1 fredette if (Dint_isinexact_to_dbl(srcp2)) { 346 1.1 fredette switch (Rounding_mode()) { 347 1.1 fredette case ROUNDPLUS: 348 1.1 fredette if (Dbl_iszero_sign(resultp1)) { 349 1.1 fredette Dbl_increment(resultp1,resultp2); 350 1.1 fredette } 351 1.1 fredette break; 352 1.1 fredette case ROUNDMINUS: 353 1.1 fredette if (Dbl_isone_sign(resultp1)) { 354 1.1 fredette Dbl_increment(resultp1,resultp2); 355 1.1 fredette } 356 1.1 fredette break; 357 1.1 fredette case ROUNDNEAREST: 358 1.1 fredette Dbl_roundnearest_from_dint(srcp2,resultp1, 359 1.1 fredette resultp2); 360 1.1 fredette } 361 1.1 fredette if (Is_inexacttrap_enabled()) { 362 1.1 fredette Dbl_copytoptr(resultp1,resultp2,dstptr); 363 1.1 fredette return(INEXACTEXCEPTION); 364 1.1 fredette } 365 1.1 fredette else Set_inexactflag(); 366 1.1 fredette } 367 1.1 fredette Dbl_copytoptr(resultp1,resultp2,dstptr); 368 1.1 fredette return(NOEXCEPTION); 369 1.1 fredette } 370