linux/arch/parisc/math-emu/fcnvxf.c
<<
>>
Prefs
   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