Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fcnvff.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/spmath/fcnvff.c $Revision: 1.1 $
26  *
27  * Purpose:
28  * Single Floating-point to Double Floating-point
29  * Double Floating-point to Single Floating-point
30  *
31  * External Interfaces:
32  * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
33  * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
34  *
35  * Internal Interfaces:
36  *
37  * Theory:
38  * <<please update with a overview of the operation of this file>>
39  *
40  * END_DESC
41 */
42 
43 
44 #include "float.h"
45 #include "sgl_float.h"
46 #include "dbl_float.h"
47 #include "cnv_float.h"
48 
49 /*
50  * Single Floating-point to Double Floating-point
51  */
52 /*ARGSUSED*/
53 int
55  sgl_floating_point *srcptr,
56  unsigned int *nullptr,
57  dbl_floating_point *dstptr,
58  unsigned int *status)
59 {
60  register unsigned int src, resultp1, resultp2;
61  register int src_exponent;
62 
63  src = *srcptr;
64  src_exponent = Sgl_exponent(src);
65  Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */
66  /*
67  * Test for NaN or infinity
68  */
69  if (src_exponent == SGL_INFINITY_EXPONENT) {
70  /*
71  * determine if NaN or infinity
72  */
73  if (Sgl_iszero_mantissa(src)) {
74  /*
75  * is infinity; want to return double infinity
76  */
77  Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
78  Dbl_copytoptr(resultp1,resultp2,dstptr);
79  return(NOEXCEPTION);
80  }
81  else {
82  /*
83  * is NaN; signaling or quiet?
84  */
85  if (Sgl_isone_signaling(src)) {
86  /* trap if INVALIDTRAP enabled */
88  return(INVALIDEXCEPTION);
89  /* make NaN quiet */
90  else {
92  Sgl_set_quiet(src);
93  }
94  }
95  /*
96  * NaN is quiet, return as double NaN
97  */
98  Dbl_setinfinity_exponent(resultp1);
99  Sgl_to_dbl_mantissa(src,resultp1,resultp2);
100  Dbl_copytoptr(resultp1,resultp2,dstptr);
101  return(NOEXCEPTION);
102  }
103  }
104  /*
105  * Test for zero or denormalized
106  */
107  if (src_exponent == 0) {
108  /*
109  * determine if zero or denormalized
110  */
111  if (Sgl_isnotzero_mantissa(src)) {
112  /*
113  * is denormalized; want to normalize
114  */
116  Sgl_leftshiftby1(src);
117  Sgl_normalize(src,src_exponent);
118  Sgl_to_dbl_exponent(src_exponent,resultp1);
119  Sgl_to_dbl_mantissa(src,resultp1,resultp2);
120  }
121  else {
122  Dbl_setzero_exponentmantissa(resultp1,resultp2);
123  }
124  Dbl_copytoptr(resultp1,resultp2,dstptr);
125  return(NOEXCEPTION);
126  }
127  /*
128  * No special cases, just complete the conversion
129  */
130  Sgl_to_dbl_exponent(src_exponent, resultp1);
131  Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
132  Dbl_copytoptr(resultp1,resultp2,dstptr);
133  return(NOEXCEPTION);
134 }
135 
136 /*
137  * Double Floating-point to Single Floating-point
138  */
139 /*ARGSUSED*/
140 int
142  dbl_floating_point *srcptr,
143  unsigned int *nullptr,
144  sgl_floating_point *dstptr,
145  unsigned int *status)
146 {
147  register unsigned int srcp1, srcp2, result;
148  register int src_exponent, dest_exponent, dest_mantissa;
149  register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
150  register boolean lsb_odd = FALSE;
151  boolean is_tiny;
152 
153  Dbl_copyfromptr(srcptr,srcp1,srcp2);
154  src_exponent = Dbl_exponent(srcp1);
155  Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */
156  /*
157  * Test for NaN or infinity
158  */
159  if (src_exponent == DBL_INFINITY_EXPONENT) {
160  /*
161  * determine if NaN or infinity
162  */
163  if (Dbl_iszero_mantissa(srcp1,srcp2)) {
164  /*
165  * is infinity; want to return single infinity
166  */
168  *dstptr = result;
169  return(NOEXCEPTION);
170  }
171  /*
172  * is NaN; signaling or quiet?
173  */
174  if (Dbl_isone_signaling(srcp1)) {
175  /* trap if INVALIDTRAP enabled */
177  else {
178  Set_invalidflag();
179  /* make NaN quiet */
180  Dbl_set_quiet(srcp1);
181  }
182  }
183  /*
184  * NaN is quiet, return as single NaN
185  */
186  Sgl_setinfinity_exponent(result);
187  Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
188  if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
189  *dstptr = result;
190  return(NOEXCEPTION);
191  }
192  /*
193  * Generate result
194  */
195  Dbl_to_sgl_exponent(src_exponent,dest_exponent);
196  if (dest_exponent > 0) {
197  Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
198  stickybit,lsb_odd);
199  }
200  else {
201  if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
203  *dstptr = result;
204  return(NOEXCEPTION);
205  }
206  if (Is_underflowtrap_enabled()) {
207  Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
208  guardbit,stickybit,lsb_odd);
209  }
210  else {
211  /* compute result, determine inexact info,
212  * and set Underflowflag if appropriate
213  */
214  Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
215  dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
216  is_tiny);
217  }
218  }
219  /*
220  * Now round result if not exact
221  */
222  if (inexact) {
223  switch (Rounding_mode()) {
224  case ROUNDPLUS:
225  if (Sgl_iszero_sign(result)) dest_mantissa++;
226  break;
227  case ROUNDMINUS:
228  if (Sgl_isone_sign(result)) dest_mantissa++;
229  break;
230  case ROUNDNEAREST:
231  if (guardbit) {
232  if (stickybit || lsb_odd) dest_mantissa++;
233  }
234  }
235  }
236  Sgl_set_exponentmantissa(result,dest_mantissa);
237 
238  /*
239  * check for mantissa overflow after rounding
240  */
241  if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
242  Sgl_isone_hidden(result)) dest_exponent++;
243 
244  /*
245  * Test for overflow
246  */
247  if (dest_exponent >= SGL_INFINITY_EXPONENT) {
248  /* trap if OVERFLOWTRAP enabled */
249  if (Is_overflowtrap_enabled()) {
250  /*
251  * Check for gross overflow
252  */
253  if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
254  return(UNIMPLEMENTEDEXCEPTION);
255 
256  /*
257  * Adjust bias of result
258  */
259  Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
260  *dstptr = result;
261  if (inexact)
264  else Set_inexactflag();
265  return(OVERFLOWEXCEPTION);
266  }
268  inexact = TRUE;
269  /* set result to infinity or largest number */
270  Sgl_setoverflow(result);
271  }
272  /*
273  * Test for underflow
274  */
275  else if (dest_exponent <= 0) {
276  /* trap if UNDERFLOWTRAP enabled */
277  if (Is_underflowtrap_enabled()) {
278  /*
279  * Check for gross underflow
280  */
281  if (dest_exponent <= -(SGL_WRAP))
282  return(UNIMPLEMENTEDEXCEPTION);
283  /*
284  * Adjust bias of result
285  */
286  Sgl_setwrapped_exponent(result,dest_exponent,unfl);
287  *dstptr = result;
288  if (inexact)
291  else Set_inexactflag();
292  return(UNDERFLOWEXCEPTION);
293  }
294  /*
295  * result is denormalized or signed zero
296  */
297  if (inexact && is_tiny) Set_underflowflag();
298 
299  }
300  else Sgl_set_exponent(result,dest_exponent);
301  *dstptr = result;
302  /*
303  * Trap if inexact trap is enabled
304  */
305  if (inexact)
307  else Set_inexactflag();
308  return(NOEXCEPTION);
309 }