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