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