linux/arch/parisc/math-emu/denormal.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/fp/denormal.c                $ Revision: $
  26 *
  27 *  Purpose:
  28 *      <<please update with a synopsis of the functionality provided by this file>>
  29 *
  30 *  External Interfaces:
  31 *      <<the following list was autogenerated, please review>>
  32 *      dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
  33 *      sgl_denormalize(sgl_opnd,inexactflag,rmode)
  34 *
  35 *  Internal Interfaces:
  36 *      <<please update>>
  37 *
  38 *  Theory:
  39 *      <<please update with a overview of the operation of this file>>
  40 *
  41 * END_DESC
  42*/
  43
  44
  45
  46#include "float.h"
  47#include "sgl_float.h"
  48#include "dbl_float.h"
  49#include "hppa.h"
  50#include <linux/kernel.h>
  51/* #include <machine/sys/mdep_private.h> */
  52
  53#undef Fpustatus_register
  54#define Fpustatus_register Fpu_register[0]
  55
  56void
  57sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
  58{
  59        unsigned int opnd;
  60        int sign, exponent;
  61        boolean guardbit = FALSE, stickybit, inexact;
  62
  63        opnd = *sgl_opnd;
  64        stickybit = *inexactflag;
  65        exponent = Sgl_exponent(opnd) - SGL_WRAP;
  66        sign = Sgl_sign(opnd);
  67        Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
  68        if (inexact) {
  69            switch (rmode) {
  70              case ROUNDPLUS:
  71                if (sign == 0) {
  72                        Sgl_increment(opnd);
  73                }
  74                break;
  75              case ROUNDMINUS:
  76                if (sign != 0) {
  77                        Sgl_increment(opnd);
  78                }
  79                break;
  80              case ROUNDNEAREST:
  81                if (guardbit && (stickybit || 
  82                       Sgl_isone_lowmantissa(opnd))) {
  83                           Sgl_increment(opnd);
  84                }
  85                break;
  86            }
  87        }
  88        Sgl_set_sign(opnd,sign);
  89        *sgl_opnd = opnd;
  90        *inexactflag = inexact;
  91        return;
  92}
  93
  94void
  95dbl_denormalize(unsigned int *dbl_opndp1,
  96        unsigned int * dbl_opndp2,
  97        boolean *inexactflag,
  98        int rmode)
  99{
 100        unsigned int opndp1, opndp2;
 101        int sign, exponent;
 102        boolean guardbit = FALSE, stickybit, inexact;
 103
 104        opndp1 = *dbl_opndp1;
 105        opndp2 = *dbl_opndp2;
 106        stickybit = *inexactflag;
 107        exponent = Dbl_exponent(opndp1) - DBL_WRAP;
 108        sign = Dbl_sign(opndp1);
 109        Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
 110        if (inexact) {
 111            switch (rmode) {
 112              case ROUNDPLUS:
 113                if (sign == 0) {
 114                        Dbl_increment(opndp1,opndp2);
 115                }
 116                break;
 117              case ROUNDMINUS:
 118                if (sign != 0) {
 119                        Dbl_increment(opndp1,opndp2);
 120                }
 121                break;
 122              case ROUNDNEAREST:
 123                if (guardbit && (stickybit || 
 124                       Dbl_isone_lowmantissap2(opndp2))) {
 125                           Dbl_increment(opndp1,opndp2);
 126                }
 127                break;
 128            }
 129        }
 130        Dbl_set_sign(opndp1,sign);
 131        *dbl_opndp1 = opndp1;
 132        *dbl_opndp2 = opndp2;
 133        *inexactflag = inexact;
 134        return;
 135}
 136