1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Linux/PA-RISC Project (http://www.parisc-linux.org/) 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Floating-point emulation code 5*1da177e4SLinus Torvalds * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 8*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 9*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 10*1da177e4SLinus Torvalds * any later version. 11*1da177e4SLinus Torvalds * 12*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 13*1da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*1da177e4SLinus Torvalds * GNU General Public License for more details. 16*1da177e4SLinus Torvalds * 17*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 18*1da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 19*1da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20*1da177e4SLinus Torvalds */ 21*1da177e4SLinus Torvalds /* 22*1da177e4SLinus Torvalds * BEGIN_DESC 23*1da177e4SLinus Torvalds * 24*1da177e4SLinus Torvalds * File: 25*1da177e4SLinus Torvalds * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $ 26*1da177e4SLinus Torvalds * 27*1da177e4SLinus Torvalds * Purpose: 28*1da177e4SLinus Torvalds * Fixed point to Floating-point Converts 29*1da177e4SLinus Torvalds * 30*1da177e4SLinus Torvalds * External Interfaces: 31*1da177e4SLinus Torvalds * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 32*1da177e4SLinus Torvalds * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 33*1da177e4SLinus Torvalds * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) 34*1da177e4SLinus Torvalds * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) 35*1da177e4SLinus Torvalds * 36*1da177e4SLinus Torvalds * Internal Interfaces: 37*1da177e4SLinus Torvalds * 38*1da177e4SLinus Torvalds * Theory: 39*1da177e4SLinus Torvalds * <<please update with a overview of the operation of this file>> 40*1da177e4SLinus Torvalds * 41*1da177e4SLinus Torvalds * END_DESC 42*1da177e4SLinus Torvalds */ 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds #include "float.h" 46*1da177e4SLinus Torvalds #include "sgl_float.h" 47*1da177e4SLinus Torvalds #include "dbl_float.h" 48*1da177e4SLinus Torvalds #include "cnv_float.h" 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds /************************************************************************ 51*1da177e4SLinus Torvalds * Fixed point to Floating-point Converts * 52*1da177e4SLinus Torvalds ************************************************************************/ 53*1da177e4SLinus Torvalds 54*1da177e4SLinus Torvalds /* 55*1da177e4SLinus Torvalds * Convert Single Unsigned Fixed to Single Floating-point format 56*1da177e4SLinus Torvalds */ 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds int 59*1da177e4SLinus Torvalds sgl_to_sgl_fcnvuf( 60*1da177e4SLinus Torvalds unsigned int *srcptr, 61*1da177e4SLinus Torvalds unsigned int *nullptr, 62*1da177e4SLinus Torvalds sgl_floating_point *dstptr, 63*1da177e4SLinus Torvalds unsigned int *status) 64*1da177e4SLinus Torvalds { 65*1da177e4SLinus Torvalds register unsigned int src, result = 0; 66*1da177e4SLinus Torvalds register int dst_exponent; 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds src = *srcptr; 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds /* Check for zero */ 71*1da177e4SLinus Torvalds if (src == 0) { 72*1da177e4SLinus Torvalds Sgl_setzero(result); 73*1da177e4SLinus Torvalds *dstptr = result; 74*1da177e4SLinus Torvalds return(NOEXCEPTION); 75*1da177e4SLinus Torvalds } 76*1da177e4SLinus Torvalds /* 77*1da177e4SLinus Torvalds * Generate exponent and normalized mantissa 78*1da177e4SLinus Torvalds */ 79*1da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 80*1da177e4SLinus Torvalds /* 81*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 82*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 83*1da177e4SLinus Torvalds * between -1 and 30. 84*1da177e4SLinus Torvalds */ 85*1da177e4SLinus Torvalds Find_ms_one_bit(src,dst_exponent); 86*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 87*1da177e4SLinus Torvalds src <<= dst_exponent+1; 88*1da177e4SLinus Torvalds Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); 89*1da177e4SLinus Torvalds Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds /* check for inexact */ 92*1da177e4SLinus Torvalds if (Suint_isinexact_to_sgl(src)) { 93*1da177e4SLinus Torvalds switch (Rounding_mode()) { 94*1da177e4SLinus Torvalds case ROUNDPLUS: 95*1da177e4SLinus Torvalds Sgl_increment(result); 96*1da177e4SLinus Torvalds break; 97*1da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 98*1da177e4SLinus Torvalds break; 99*1da177e4SLinus Torvalds case ROUNDNEAREST: 100*1da177e4SLinus Torvalds Sgl_roundnearest_from_suint(src,result); 101*1da177e4SLinus Torvalds break; 102*1da177e4SLinus Torvalds } 103*1da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 104*1da177e4SLinus Torvalds *dstptr = result; 105*1da177e4SLinus Torvalds return(INEXACTEXCEPTION); 106*1da177e4SLinus Torvalds } 107*1da177e4SLinus Torvalds else Set_inexactflag(); 108*1da177e4SLinus Torvalds } 109*1da177e4SLinus Torvalds *dstptr = result; 110*1da177e4SLinus Torvalds return(NOEXCEPTION); 111*1da177e4SLinus Torvalds } 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds /* 114*1da177e4SLinus Torvalds * Single Unsigned Fixed to Double Floating-point 115*1da177e4SLinus Torvalds */ 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds int 118*1da177e4SLinus Torvalds sgl_to_dbl_fcnvuf( 119*1da177e4SLinus Torvalds unsigned int *srcptr, 120*1da177e4SLinus Torvalds unsigned int *nullptr, 121*1da177e4SLinus Torvalds dbl_floating_point *dstptr, 122*1da177e4SLinus Torvalds unsigned int *status) 123*1da177e4SLinus Torvalds { 124*1da177e4SLinus Torvalds register int dst_exponent; 125*1da177e4SLinus Torvalds register unsigned int src, resultp1 = 0, resultp2 = 0; 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds src = *srcptr; 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds /* Check for zero */ 130*1da177e4SLinus Torvalds if (src == 0) { 131*1da177e4SLinus Torvalds Dbl_setzero(resultp1,resultp2); 132*1da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 133*1da177e4SLinus Torvalds return(NOEXCEPTION); 134*1da177e4SLinus Torvalds } 135*1da177e4SLinus Torvalds /* 136*1da177e4SLinus Torvalds * Generate exponent and normalized mantissa 137*1da177e4SLinus Torvalds */ 138*1da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 139*1da177e4SLinus Torvalds /* 140*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 141*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 142*1da177e4SLinus Torvalds * between -1 and 30. 143*1da177e4SLinus Torvalds */ 144*1da177e4SLinus Torvalds Find_ms_one_bit(src,dst_exponent); 145*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 146*1da177e4SLinus Torvalds src <<= dst_exponent+1; 147*1da177e4SLinus Torvalds Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); 148*1da177e4SLinus Torvalds Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); 149*1da177e4SLinus Torvalds Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); 150*1da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 151*1da177e4SLinus Torvalds return(NOEXCEPTION); 152*1da177e4SLinus Torvalds } 153*1da177e4SLinus Torvalds 154*1da177e4SLinus Torvalds /* 155*1da177e4SLinus Torvalds * Double Unsigned Fixed to Single Floating-point 156*1da177e4SLinus Torvalds */ 157*1da177e4SLinus Torvalds 158*1da177e4SLinus Torvalds int 159*1da177e4SLinus Torvalds dbl_to_sgl_fcnvuf( 160*1da177e4SLinus Torvalds dbl_unsigned *srcptr, 161*1da177e4SLinus Torvalds unsigned int *nullptr, 162*1da177e4SLinus Torvalds sgl_floating_point *dstptr, 163*1da177e4SLinus Torvalds unsigned int *status) 164*1da177e4SLinus Torvalds { 165*1da177e4SLinus Torvalds int dst_exponent; 166*1da177e4SLinus Torvalds unsigned int srcp1, srcp2, result = 0; 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds Duint_copyfromptr(srcptr,srcp1,srcp2); 169*1da177e4SLinus Torvalds 170*1da177e4SLinus Torvalds /* Check for zero */ 171*1da177e4SLinus Torvalds if (srcp1 == 0 && srcp2 == 0) { 172*1da177e4SLinus Torvalds Sgl_setzero(result); 173*1da177e4SLinus Torvalds *dstptr = result; 174*1da177e4SLinus Torvalds return(NOEXCEPTION); 175*1da177e4SLinus Torvalds } 176*1da177e4SLinus Torvalds /* 177*1da177e4SLinus Torvalds * Generate exponent and normalized mantissa 178*1da177e4SLinus Torvalds */ 179*1da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 180*1da177e4SLinus Torvalds if (srcp1 == 0) { 181*1da177e4SLinus Torvalds /* 182*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 183*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 184*1da177e4SLinus Torvalds * between -1 and 30. 185*1da177e4SLinus Torvalds */ 186*1da177e4SLinus Torvalds Find_ms_one_bit(srcp2,dst_exponent); 187*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 188*1da177e4SLinus Torvalds srcp1 = srcp2 << dst_exponent+1; 189*1da177e4SLinus Torvalds srcp2 = 0; 190*1da177e4SLinus Torvalds /* 191*1da177e4SLinus Torvalds * since msb set is in second word, need to 192*1da177e4SLinus Torvalds * adjust bit position count 193*1da177e4SLinus Torvalds */ 194*1da177e4SLinus Torvalds dst_exponent += 32; 195*1da177e4SLinus Torvalds } 196*1da177e4SLinus Torvalds else { 197*1da177e4SLinus Torvalds /* 198*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 199*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 200*1da177e4SLinus Torvalds * between -1 and 30. 201*1da177e4SLinus Torvalds * 202*1da177e4SLinus Torvalds */ 203*1da177e4SLinus Torvalds Find_ms_one_bit(srcp1,dst_exponent); 204*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 205*1da177e4SLinus Torvalds if (dst_exponent >= 0) { 206*1da177e4SLinus Torvalds Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 207*1da177e4SLinus Torvalds srcp1); 208*1da177e4SLinus Torvalds srcp2 <<= dst_exponent+1; 209*1da177e4SLinus Torvalds } 210*1da177e4SLinus Torvalds } 211*1da177e4SLinus Torvalds Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); 212*1da177e4SLinus Torvalds Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds /* check for inexact */ 215*1da177e4SLinus Torvalds if (Duint_isinexact_to_sgl(srcp1,srcp2)) { 216*1da177e4SLinus Torvalds switch (Rounding_mode()) { 217*1da177e4SLinus Torvalds case ROUNDPLUS: 218*1da177e4SLinus Torvalds Sgl_increment(result); 219*1da177e4SLinus Torvalds break; 220*1da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 221*1da177e4SLinus Torvalds break; 222*1da177e4SLinus Torvalds case ROUNDNEAREST: 223*1da177e4SLinus Torvalds Sgl_roundnearest_from_duint(srcp1,srcp2,result); 224*1da177e4SLinus Torvalds break; 225*1da177e4SLinus Torvalds } 226*1da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 227*1da177e4SLinus Torvalds *dstptr = result; 228*1da177e4SLinus Torvalds return(INEXACTEXCEPTION); 229*1da177e4SLinus Torvalds } 230*1da177e4SLinus Torvalds else Set_inexactflag(); 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds *dstptr = result; 233*1da177e4SLinus Torvalds return(NOEXCEPTION); 234*1da177e4SLinus Torvalds } 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds /* 237*1da177e4SLinus Torvalds * Double Unsigned Fixed to Double Floating-point 238*1da177e4SLinus Torvalds */ 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds int 241*1da177e4SLinus Torvalds dbl_to_dbl_fcnvuf( 242*1da177e4SLinus Torvalds dbl_unsigned *srcptr, 243*1da177e4SLinus Torvalds unsigned int *nullptr, 244*1da177e4SLinus Torvalds dbl_floating_point *dstptr, 245*1da177e4SLinus Torvalds unsigned int *status) 246*1da177e4SLinus Torvalds { 247*1da177e4SLinus Torvalds register int dst_exponent; 248*1da177e4SLinus Torvalds register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds Duint_copyfromptr(srcptr,srcp1,srcp2); 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds /* Check for zero */ 253*1da177e4SLinus Torvalds if (srcp1 == 0 && srcp2 ==0) { 254*1da177e4SLinus Torvalds Dbl_setzero(resultp1,resultp2); 255*1da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 256*1da177e4SLinus Torvalds return(NOEXCEPTION); 257*1da177e4SLinus Torvalds } 258*1da177e4SLinus Torvalds /* 259*1da177e4SLinus Torvalds * Generate exponent and normalized mantissa 260*1da177e4SLinus Torvalds */ 261*1da177e4SLinus Torvalds dst_exponent = 16; /* initialize for normalization */ 262*1da177e4SLinus Torvalds if (srcp1 == 0) { 263*1da177e4SLinus Torvalds /* 264*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 265*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 266*1da177e4SLinus Torvalds * between -1 and 30. 267*1da177e4SLinus Torvalds */ 268*1da177e4SLinus Torvalds Find_ms_one_bit(srcp2,dst_exponent); 269*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 270*1da177e4SLinus Torvalds srcp1 = srcp2 << dst_exponent+1; 271*1da177e4SLinus Torvalds srcp2 = 0; 272*1da177e4SLinus Torvalds /* 273*1da177e4SLinus Torvalds * since msb set is in second word, need to 274*1da177e4SLinus Torvalds * adjust bit position count 275*1da177e4SLinus Torvalds */ 276*1da177e4SLinus Torvalds dst_exponent += 32; 277*1da177e4SLinus Torvalds } 278*1da177e4SLinus Torvalds else { 279*1da177e4SLinus Torvalds /* 280*1da177e4SLinus Torvalds * Check word for most significant bit set. Returns 281*1da177e4SLinus Torvalds * a value in dst_exponent indicating the bit position, 282*1da177e4SLinus Torvalds * between -1 and 30. 283*1da177e4SLinus Torvalds */ 284*1da177e4SLinus Torvalds Find_ms_one_bit(srcp1,dst_exponent); 285*1da177e4SLinus Torvalds /* left justify source, with msb at bit position 0 */ 286*1da177e4SLinus Torvalds if (dst_exponent >= 0) { 287*1da177e4SLinus Torvalds Variable_shift_double(srcp1,srcp2,(31-dst_exponent), 288*1da177e4SLinus Torvalds srcp1); 289*1da177e4SLinus Torvalds srcp2 <<= dst_exponent+1; 290*1da177e4SLinus Torvalds } 291*1da177e4SLinus Torvalds } 292*1da177e4SLinus Torvalds Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); 293*1da177e4SLinus Torvalds Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); 294*1da177e4SLinus Torvalds Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds /* check for inexact */ 297*1da177e4SLinus Torvalds if (Duint_isinexact_to_dbl(srcp2)) { 298*1da177e4SLinus Torvalds switch (Rounding_mode()) { 299*1da177e4SLinus Torvalds case ROUNDPLUS: 300*1da177e4SLinus Torvalds Dbl_increment(resultp1,resultp2); 301*1da177e4SLinus Torvalds break; 302*1da177e4SLinus Torvalds case ROUNDMINUS: /* never negative */ 303*1da177e4SLinus Torvalds break; 304*1da177e4SLinus Torvalds case ROUNDNEAREST: 305*1da177e4SLinus Torvalds Dbl_roundnearest_from_duint(srcp2,resultp1, 306*1da177e4SLinus Torvalds resultp2); 307*1da177e4SLinus Torvalds break; 308*1da177e4SLinus Torvalds } 309*1da177e4SLinus Torvalds if (Is_inexacttrap_enabled()) { 310*1da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 311*1da177e4SLinus Torvalds return(INEXACTEXCEPTION); 312*1da177e4SLinus Torvalds } 313*1da177e4SLinus Torvalds else Set_inexactflag(); 314*1da177e4SLinus Torvalds } 315*1da177e4SLinus Torvalds Dbl_copytoptr(resultp1,resultp2,dstptr); 316*1da177e4SLinus Torvalds return(NOEXCEPTION); 317*1da177e4SLinus Torvalds } 318*1da177e4SLinus Torvalds 319