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