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/fcnvuf.c $Revision: 1.1 $ 26 * 27 * Purpose: 28 * Fixed point to Floating-point Converts 29 * 30 * External Interfaces: 31 * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 32 * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 33 * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 34 * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 35 * 36 * Internal Interfaces: 37 * 38 * Theory: 39 * <<please update with a overview of the operation of this file>> 40 * 41 * END_DESC 42 */ 43 44 45 #include "float.h" 46 #include "sgl_float.h" 47 #include "dbl_float.h" 48 #include "cnv_float.h" 49 50 /************************************************************************ 51 * Fixed point to Floating-point Converts * 52 ************************************************************************/ 53 54 /* 55 * Convert Single Unsigned Fixed to Single Floating-point format 56 */ 57 58 int 59 sgl_to_sgl_fcnvuf( 60 unsigned int *srcptr, 61 unsigned int *nullptr, 62 sgl_floating_point *dstptr, 63 unsigned int *status) 64 { 65 register unsigned int src, result = 0; 66 register int dst_exponent; 67 68 src = *srcptr; 69 70 /* Check for zero */ 71 if (src == 0) { 72 Sgl_setzero(result); 73 *dstptr = result; 74 return(NOEXCEPTION); 75 } 76 /* 77 * Generate exponent and normalized mantissa 78 */ 79 dst_exponent = 16; /* initialize for normalization */ 80 /* 81 * Check word for most significant bit set. Returns 82 * a value in dst_exponent indicating the bit position, 83 * between -1 and 30. 84 */ 85 Find_ms_one_bit(src,dst_exponent); 86 /* left justify source, with msb at bit position 0 */ 87 src <<= dst_exponent+1; 88 Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); 89 Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 90 91 /* check for inexact */ 92 if (Suint_isinexact_to_sgl(src)) { 93 switch (Rounding_mode()) { 94 case ROUNDPLUS: 95 Sgl_increment(result); 96 break; 97 case ROUNDMINUS: /* never negative */ 98 break; 99 case ROUNDNEAREST: 100 Sgl_roundnearest_from_suint(src,result); 101 break; 102 } 103 if (Is_inexacttrap_enabled()) { 104 *dstptr = result; 105 return(INEXACTEXCEPTION); 106 } 107 else Set_inexactflag(); 108 } 109 *dstptr = result; 110 return(NOEXCEPTION); 111 } 112 113 /* 114 * Single Unsigned Fixed to Double Floating-point 115 */ 116 117 int 118 sgl_to_dbl_fcnvuf( 119 unsigned int *srcptr, 120 unsigned int *nullptr, 121 dbl_floating_point *dstptr, 122 unsigned int *status) 123 { 124 register int dst_exponent; 125 register unsigned int src, resultp1 = 0, resultp2 = 0; 126 127 src = *srcptr; 128 129 /* Check for zero */ 130 if (src == 0) { 131 Dbl_setzero(resultp1,resultp2); 132 Dbl_copytoptr(resultp1,resultp2,dstptr); 133 return(NOEXCEPTION); 134 } 135 /* 136 * Generate exponent and normalized mantissa 137 */ 138 dst_exponent = 16; /* initialize for normalization */ 139 /* 140 * Check word for most significant bit set. Returns 141 * a value in dst_exponent indicating the bit position, 142 * between -1 and 30. 143 */ 144 Find_ms_one_bit(src,dst_exponent); 145 /* left justify source, with msb at bit position 0 */ 146 src <<= dst_exponent+1; 147 Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); 148 Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); 149 Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 150 Dbl_copytoptr(resultp1,resultp2,dstptr); 151 return(NOEXCEPTION); 152 } 153 154 /* 155 * Double Unsigned Fixed to Single Floating-point 156 */ 157 158 int 159 dbl_to_sgl_fcnvuf( 160 dbl_unsigned *srcptr, 161 unsigned int *nullptr, 162 sgl_floating_point *dstptr, 163 unsigned int *status) 164 { 165 int dst_exponent; 166 unsigned int srcp1, srcp2, result = 0; 167 168 Duint_copyfromptr(srcptr,srcp1,srcp2); 169 170 /* Check for zero */ 171 if (srcp1 == 0 && srcp2 == 0) { 172 Sgl_setzero(result); 173 *dstptr = result; 174 return(NOEXCEPTION); 175 } 176 /* 177 * Generate exponent and normalized mantissa 178 */ 179 dst_exponent = 16; /* initialize for normalization */ 180 if (srcp1 == 0) { 181 /* 182 * Check word for most significant bit set. Returns 183 * a value in dst_exponent indicating the bit position, 184 * between -1 and 30. 185 */ 186 Find_ms_one_bit(srcp2,dst_exponent); 187 /* left justify source, with msb at bit position 0 */ 188 srcp1 = srcp2 << dst_exponent+1; 189 srcp2 = 0; 190 /* 191 * since msb set is in second word, need to 192 * adjust bit position count 193 */ 194 dst_exponent += 32; 195 } 196 else { 197 /* 198 * Check word for most significant bit set. Returns 199 * a value in dst_exponent indicating the bit position, 200 * between -1 and 30. 201 * 202 */ 203 Find_ms_one_bit(srcp1,dst_exponent); 204 /* left justify source, with msb at bit position 0 */ 205 if (dst_exponent >= 0) { 206 Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 207 srcp1); 208 srcp2 <<= dst_exponent+1; 209 } 210 } 211 Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); 212 Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 213 214 /* check for inexact */ 215 if (Duint_isinexact_to_sgl(srcp1,srcp2)) { 216 switch (Rounding_mode()) { 217 case ROUNDPLUS: 218 Sgl_increment(result); 219 break; 220 case ROUNDMINUS: /* never negative */ 221 break; 222 case ROUNDNEAREST: 223 Sgl_roundnearest_from_duint(srcp1,srcp2,result); 224 break; 225 } 226 if (Is_inexacttrap_enabled()) { 227 *dstptr = result; 228 return(INEXACTEXCEPTION); 229 } 230 else Set_inexactflag(); 231 } 232 *dstptr = result; 233 return(NOEXCEPTION); 234 } 235 236 /* 237 * Double Unsigned Fixed to Double Floating-point 238 */ 239 240 int 241 dbl_to_dbl_fcnvuf( 242 dbl_unsigned *srcptr, 243 unsigned int *nullptr, 244 dbl_floating_point *dstptr, 245 unsigned int *status) 246 { 247 register int dst_exponent; 248 register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; 249 250 Duint_copyfromptr(srcptr,srcp1,srcp2); 251 252 /* Check for zero */ 253 if (srcp1 == 0 && srcp2 ==0) { 254 Dbl_setzero(resultp1,resultp2); 255 Dbl_copytoptr(resultp1,resultp2,dstptr); 256 return(NOEXCEPTION); 257 } 258 /* 259 * Generate exponent and normalized mantissa 260 */ 261 dst_exponent = 16; /* initialize for normalization */ 262 if (srcp1 == 0) { 263 /* 264 * Check word for most significant bit set. Returns 265 * a value in dst_exponent indicating the bit position, 266 * between -1 and 30. 267 */ 268 Find_ms_one_bit(srcp2,dst_exponent); 269 /* left justify source, with msb at bit position 0 */ 270 srcp1 = srcp2 << dst_exponent+1; 271 srcp2 = 0; 272 /* 273 * since msb set is in second word, need to 274 * adjust bit position count 275 */ 276 dst_exponent += 32; 277 } 278 else { 279 /* 280 * Check word for most significant bit set. Returns 281 * a value in dst_exponent indicating the bit position, 282 * between -1 and 30. 283 */ 284 Find_ms_one_bit(srcp1,dst_exponent); 285 /* left justify source, with msb at bit position 0 */ 286 if (dst_exponent >= 0) { 287 Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 288 srcp1); 289 srcp2 <<= dst_exponent+1; 290 } 291 } 292 Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); 293 Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); 294 Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 295 296 /* check for inexact */ 297 if (Duint_isinexact_to_dbl(srcp2)) { 298 switch (Rounding_mode()) { 299 case ROUNDPLUS: 300 Dbl_increment(resultp1,resultp2); 301 break; 302 case ROUNDMINUS: /* never negative */ 303 break; 304 case ROUNDNEAREST: 305 Dbl_roundnearest_from_duint(srcp2,resultp1, 306 resultp2); 307 break; 308 } 309 if (Is_inexacttrap_enabled()) { 310 Dbl_copytoptr(resultp1,resultp2,dstptr); 311 return(INEXACTEXCEPTION); 312 } 313 else Set_inexactflag(); 314 } 315 Dbl_copytoptr(resultp1,resultp2,dstptr); 316 return(NOEXCEPTION); 317 } 318 319