Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
denormal.c
Go to the documentation of this file.
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) <[email protected]>
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 
56 void
57 sgl_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 
94 void
95 dbl_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 }