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/fcnvxf.c $Revision: 1.1 $ 26 * 27 * Purpose: 28 * Single Fixed-point to Single Floating-point 29 * Single Fixed-point to Double Floating-point 30 * Double Fixed-point to Single Floating-point 31 * Double Fixed-point to Double Floating-point 32 * 33 * External Interfaces: 34 * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) 35 * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) 36 * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) 37 * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) 38 * 39 * Internal Interfaces: 40 * 41 * Theory: 42 * <<please update with a overview of the operation of this file>> 43 * 44 * END_DESC 45*/ 46 47 48#include "float.h" 49#include "sgl_float.h" 50#include "dbl_float.h" 51#include "cnv_float.h" 52 53/* 54 * Convert single fixed-point to single floating-point format 55 */ 56 57int 58sgl_to_sgl_fcnvxf( 59 int *srcptr, 60 unsigned int *nullptr, 61 sgl_floating_point *dstptr, 62 unsigned int *status) 63{ 64 register int src, dst_exponent; 65 register unsigned int result = 0; 66 67 src = *srcptr; 68 /* 69 * set sign bit of result and get magnitude of source 70 */ 71 if (src < 0) { 72 Sgl_setone_sign(result); 73 Int_negate(src); 74 } 75 else { 76 Sgl_setzero_sign(result); 77 /* Check for zero */ 78 if (src == 0) { 79 Sgl_setzero(result); 80 *dstptr = result; 81 return(NOEXCEPTION); 82 } 83 } 84 /* 85 * Generate exponent and normalized mantissa 86 */ 87 dst_exponent = 16; /* initialize for normalization */ 88 /* 89 * Check word for most significant bit set. Returns 90 * a value in dst_exponent indicating the bit position, 91 * between -1 and 30. 92 */ 93 Find_ms_one_bit(src,dst_exponent); 94 /* left justify source, with msb at bit position 1 */ 95 if (dst_exponent >= 0) src <<= dst_exponent; 96 else src = 1 << 30; 97 Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); 98 Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 99 100 /* check for inexact */ 101 if (Int_isinexact_to_sgl(src)) { 102 switch (Rounding_mode()) { 103 case ROUNDPLUS: 104 if (Sgl_iszero_sign(result)) 105 Sgl_increment(result); 106 break; 107 case ROUNDMINUS: 108 if (Sgl_isone_sign(result)) 109 Sgl_increment(result); 110 break; 111 case ROUNDNEAREST: 112 Sgl_roundnearest_from_int(src,result); 113 } 114 if (Is_inexacttrap_enabled()) { 115 *dstptr = result; 116 return(INEXACTEXCEPTION); 117 } 118 else Set_inexactflag(); 119 } 120 *dstptr = result; 121 return(NOEXCEPTION); 122} 123 124/* 125 * Single Fixed-point to Double Floating-point 126 */ 127 128int 129sgl_to_dbl_fcnvxf( 130 int *srcptr, 131 unsigned int *nullptr, 132 dbl_floating_point *dstptr, 133 unsigned int *status) 134{ 135 register int src, dst_exponent; 136 register unsigned int resultp1 = 0, resultp2 = 0; 137 138 src = *srcptr; 139 /* 140 * set sign bit of result and get magnitude of source 141 */ 142 if (src < 0) { 143 Dbl_setone_sign(resultp1); 144 Int_negate(src); 145 } 146 else { 147 Dbl_setzero_sign(resultp1); 148 /* Check for zero */ 149 if (src == 0) { 150 Dbl_setzero(resultp1,resultp2); 151 Dbl_copytoptr(resultp1,resultp2,dstptr); 152 return(NOEXCEPTION); 153 } 154 } 155 /* 156 * Generate exponent and normalized mantissa 157 */ 158 dst_exponent = 16; /* initialize for normalization */ 159 /* 160 * Check word for most significant bit set. Returns 161 * a value in dst_exponent indicating the bit position, 162 * between -1 and 30. 163 */ 164 Find_ms_one_bit(src,dst_exponent); 165 /* left justify source, with msb at bit position 1 */ 166 if (dst_exponent >= 0) src <<= dst_exponent; 167 else src = 1 << 30; 168 Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1); 169 Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH)); 170 Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 171 Dbl_copytoptr(resultp1,resultp2,dstptr); 172 return(NOEXCEPTION); 173} 174 175/* 176 * Double Fixed-point to Single Floating-point 177 */ 178 179int 180dbl_to_sgl_fcnvxf( 181 dbl_integer *srcptr, 182 unsigned int *nullptr, 183 sgl_floating_point *dstptr, 184 unsigned int *status) 185{ 186 int dst_exponent, srcp1; 187 unsigned int result = 0, srcp2; 188 189 Dint_copyfromptr(srcptr,srcp1,srcp2); 190 /* 191 * set sign bit of result and get magnitude of source 192 */ 193 if (srcp1 < 0) { 194 Sgl_setone_sign(result); 195 Dint_negate(srcp1,srcp2); 196 } 197 else { 198 Sgl_setzero_sign(result); 199 /* Check for zero */ 200 if (srcp1 == 0 && srcp2 == 0) { 201 Sgl_setzero(result); 202 *dstptr = result; 203 return(NOEXCEPTION); 204 } 205 } 206 /* 207 * Generate exponent and normalized mantissa 208 */ 209 dst_exponent = 16; /* initialize for normalization */ 210 if (srcp1 == 0) { 211 /* 212 * Check word for most significant bit set. Returns 213 * a value in dst_exponent indicating the bit position, 214 * between -1 and 30. 215 */ 216 Find_ms_one_bit(srcp2,dst_exponent); 217 /* left justify source, with msb at bit position 1 */ 218 if (dst_exponent >= 0) { 219 srcp1 = srcp2 << dst_exponent; 220 srcp2 = 0; 221 } 222 else { 223 srcp1 = srcp2 >> 1; 224 srcp2 <<= 31; 225 } 226 /* 227 * since msb set is in second word, need to 228 * adjust bit position count 229 */ 230 dst_exponent += 32; 231 } 232 else { 233 /* 234 * Check word for most significant bit set. Returns 235 * a value in dst_exponent indicating the bit position, 236 * between -1 and 30. 237 * 238 */ 239 Find_ms_one_bit(srcp1,dst_exponent); 240 /* left justify source, with msb at bit position 1 */ 241 if (dst_exponent > 0) { 242 Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 243 srcp1); 244 srcp2 <<= dst_exponent; 245 } 246 /* 247 * If dst_exponent = 0, we don't need to shift anything. 248 * If dst_exponent = -1, src = - 2**63 so we won't need to 249 * shift srcp2. 250 */ 251 else srcp1 >>= -(dst_exponent); 252 } 253 Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1); 254 Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 255 256 /* check for inexact */ 257 if (Dint_isinexact_to_sgl(srcp1,srcp2)) { 258 switch (Rounding_mode()) { 259 case ROUNDPLUS: 260 if (Sgl_iszero_sign(result)) 261 Sgl_increment(result); 262 break; 263 case ROUNDMINUS: 264 if (Sgl_isone_sign(result)) 265 Sgl_increment(result); 266 break; 267 case ROUNDNEAREST: 268 Sgl_roundnearest_from_dint(srcp1,srcp2,result); 269 } 270 if (Is_inexacttrap_enabled()) { 271 *dstptr = result; 272 return(INEXACTEXCEPTION); 273 } 274 else Set_inexactflag(); 275 } 276 *dstptr = result; 277 return(NOEXCEPTION); 278} 279 280/* 281 * Double Fixed-point to Double Floating-point 282 */ 283 284int 285dbl_to_dbl_fcnvxf( 286 dbl_integer *srcptr, 287 unsigned int *nullptr, 288 dbl_floating_point *dstptr, 289 unsigned int *status) 290{ 291 register int srcp1, dst_exponent; 292 register unsigned int srcp2, resultp1 = 0, resultp2 = 0; 293 294 Dint_copyfromptr(srcptr,srcp1,srcp2); 295 /* 296 * set sign bit of result and get magnitude of source 297 */ 298 if (srcp1 < 0) { 299 Dbl_setone_sign(resultp1); 300 Dint_negate(srcp1,srcp2); 301 } 302 else { 303 Dbl_setzero_sign(resultp1); 304 /* Check for zero */ 305 if (srcp1 == 0 && srcp2 ==0) { 306 Dbl_setzero(resultp1,resultp2); 307 Dbl_copytoptr(resultp1,resultp2,dstptr); 308 return(NOEXCEPTION); 309 } 310 } 311 /* 312 * Generate exponent and normalized mantissa 313 */ 314 dst_exponent = 16; /* initialize for normalization */ 315 if (srcp1 == 0) { 316 /* 317 * Check word for most significant bit set. Returns 318 * a value in dst_exponent indicating the bit position, 319 * between -1 and 30. 320 */ 321 Find_ms_one_bit(srcp2,dst_exponent); 322 /* left justify source, with msb at bit position 1 */ 323 if (dst_exponent >= 0) { 324 srcp1 = srcp2 << dst_exponent; 325 srcp2 = 0; 326 } 327 else { 328 srcp1 = srcp2 >> 1; 329 srcp2 <<= 31; 330 } 331 /* 332 * since msb set is in second word, need to 333 * adjust bit position count 334 */ 335 dst_exponent += 32; 336 } 337 else { 338 /* 339 * Check word for most significant bit set. Returns 340 * a value in dst_exponent indicating the bit position, 341 * between -1 and 30. 342 */ 343 Find_ms_one_bit(srcp1,dst_exponent); 344 /* left justify source, with msb at bit position 1 */ 345 if (dst_exponent > 0) { 346 Variable_shift_double(srcp1,srcp2,(32-dst_exponent), 347 srcp1); 348 srcp2 <<= dst_exponent; 349 } 350 /* 351 * If dst_exponent = 0, we don't need to shift anything. 352 * If dst_exponent = -1, src = - 2**63 so we won't need to 353 * shift srcp2. 354 */ 355 else srcp1 >>= -(dst_exponent); 356 } 357 Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); 358 Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); 359 Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 360 361 /* check for inexact */ 362 if (Dint_isinexact_to_dbl(srcp2)) { 363 switch (Rounding_mode()) { 364 case ROUNDPLUS: 365 if (Dbl_iszero_sign(resultp1)) { 366 Dbl_increment(resultp1,resultp2); 367 } 368 break; 369 case ROUNDMINUS: 370 if (Dbl_isone_sign(resultp1)) { 371 Dbl_increment(resultp1,resultp2); 372 } 373 break; 374 case ROUNDNEAREST: 375 Dbl_roundnearest_from_dint(srcp2,resultp1, 376 resultp2); 377 } 378 if (Is_inexacttrap_enabled()) { 379 Dbl_copytoptr(resultp1,resultp2,dstptr); 380 return(INEXACTEXCEPTION); 381 } 382 else Set_inexactflag(); 383 } 384 Dbl_copytoptr(resultp1,resultp2,dstptr); 385 return(NOEXCEPTION); 386} 387