Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fcnvfu.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/fcnvfu.c $Revision: 1.1 $
26  *
27  * Purpose:
28  * Floating-point to Unsigned Fixed-point Converts
29  *
30  * External Interfaces:
31  * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
32  * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
33  * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
34  * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
35  *
36  * Internal Interfaces:
37  *
38  * Theory:
39  * <<please update with a overview of the operation of this file>>
40  *
41  * END_DESC
42 */
43 
44 
45 #include "float.h"
46 #include "sgl_float.h"
47 #include "dbl_float.h"
48 #include "cnv_float.h"
49 
50 /************************************************************************
51  * Floating-point to Unsigned Fixed-point Converts *
52  ************************************************************************/
53 
54 /*
55  * Single Floating-point to Single Unsigned Fixed
56  */
57 /*ARGSUSED*/
58 int
60  sgl_floating_point *srcptr,
61  unsigned int *nullptr,
62  unsigned int *dstptr,
63  unsigned int *status)
64 {
65  register unsigned int src, result;
66  register int src_exponent;
67  register boolean inexact = FALSE;
68 
69  src = *srcptr;
70  src_exponent = Sgl_exponent(src) - SGL_BIAS;
71 
72  /*
73  * Test for overflow
74  */
75  if (src_exponent > SGL_FX_MAX_EXP + 1) {
76  if (Sgl_isone_sign(src)) {
77  result = 0;
78  } else {
79  result = 0xffffffff;
80  }
81  if (Is_invalidtrap_enabled()) {
82  return(INVALIDEXCEPTION);
83  }
85  *dstptr = result;
86  return(NOEXCEPTION);
87  }
88  /*
89  * Generate result
90  */
91  if (src_exponent >= 0) {
92  /*
93  * Check sign.
94  * If negative, trap unimplemented.
95  */
96  if (Sgl_isone_sign(src)) {
97  result = 0;
98  if (Is_invalidtrap_enabled()) {
99  return(INVALIDEXCEPTION);
100  }
101  Set_invalidflag();
102  *dstptr = result;
103  return(NOEXCEPTION);
104  }
106  Suint_from_sgl_mantissa(src,src_exponent,result);
107 
108  /* check for inexact */
109  if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
110  inexact = TRUE;
111  /* round result */
112  switch (Rounding_mode()) {
113  case ROUNDPLUS:
114  result++;
115  break;
116  case ROUNDMINUS: /* never negative */
117  break;
118  case ROUNDNEAREST:
119  if (Sgl_isone_roundbit(src,src_exponent) &&
120  (Sgl_isone_stickybit(src,src_exponent) ||
121  (result & 1))) {
122  result++;
123  }
124  break;
125  }
126  }
127  } else {
128  result = 0;
129 
130  /* check for inexact */
132  inexact = TRUE;
133  /* round result */
134  switch (Rounding_mode()) {
135  case ROUNDPLUS:
136  if (Sgl_iszero_sign(src)) {
137  result++;
138  }
139  break;
140  case ROUNDMINUS:
141  if (Sgl_isone_sign(src)) {
142  result = 0;
143  if (Is_invalidtrap_enabled()) {
144  return(INVALIDEXCEPTION);
145  }
146  Set_invalidflag();
147  inexact = FALSE;
148  }
149  break;
150  case ROUNDNEAREST:
151  if (src_exponent == -1 &&
152  Sgl_isnotzero_mantissa(src)) {
153  if (Sgl_isone_sign(src)) {
154  result = 0;
155  if (Is_invalidtrap_enabled()) {
156  return(INVALIDEXCEPTION);
157  }
158  Set_invalidflag();
159  inexact = FALSE;
160  }
161  else result++;
162  }
163  break;
164  }
165  }
166  }
167  *dstptr = result;
168  if (inexact) {
170  else Set_inexactflag();
171  }
172  return(NOEXCEPTION);
173 }
174 
175 /*
176  * Single Floating-point to Double Unsigned Fixed
177  */
178 /*ARGSUSED*/
179 int
181  sgl_floating_point *srcptr,
182  unsigned int *nullptr,
183  dbl_unsigned *dstptr,
184  unsigned int *status)
185 {
186  register int src_exponent;
187  register unsigned int src, resultp1, resultp2;
188  register boolean inexact = FALSE;
189 
190  src = *srcptr;
191  src_exponent = Sgl_exponent(src) - SGL_BIAS;
192 
193  /*
194  * Test for overflow
195  */
196  if (src_exponent > DBL_FX_MAX_EXP + 1) {
197  if (Sgl_isone_sign(src)) {
198  resultp1 = resultp2 = 0;
199  } else {
200  resultp1 = resultp2 = 0xffffffff;
201  }
202  if (Is_invalidtrap_enabled()) {
203  return(INVALIDEXCEPTION);
204  }
205  Set_invalidflag();
206  Duint_copytoptr(resultp1,resultp2,dstptr);
207  return(NOEXCEPTION);
208  }
209  /*
210  * Generate result
211  */
212  if (src_exponent >= 0) {
213  /*
214  * Check sign.
215  * If negative, trap unimplemented.
216  */
217  if (Sgl_isone_sign(src)) {
218  resultp1 = resultp2 = 0;
219  if (Is_invalidtrap_enabled()) {
220  return(INVALIDEXCEPTION);
221  }
222  Set_invalidflag();
223  Duint_copytoptr(resultp1,resultp2,dstptr);
224  return(NOEXCEPTION);
225  }
227  Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
228 
229  /* check for inexact */
230  if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
231  inexact = TRUE;
232  /* round result */
233  switch (Rounding_mode()) {
234  case ROUNDPLUS:
235  Duint_increment(resultp1,resultp2);
236  break;
237  case ROUNDMINUS: /* never negative */
238  break;
239  case ROUNDNEAREST:
240  if (Sgl_isone_roundbit(src,src_exponent) &&
241  (Sgl_isone_stickybit(src,src_exponent) ||
242  Duint_isone_lowp2(resultp2))) {
243  Duint_increment(resultp1,resultp2);
244  }
245  break;
246  }
247  }
248  } else {
249  Duint_setzero(resultp1,resultp2);
250 
251  /* check for inexact */
253  inexact = TRUE;
254  /* round result */
255  switch (Rounding_mode()) {
256  case ROUNDPLUS:
257  if (Sgl_iszero_sign(src)) {
258  Duint_increment(resultp1,resultp2);
259  }
260  break;
261  case ROUNDMINUS:
262  if (Sgl_isone_sign(src)) {
263  resultp1 = resultp2 = 0;
264  if (Is_invalidtrap_enabled()) {
265  return(INVALIDEXCEPTION);
266  }
267  Set_invalidflag();
268  inexact = FALSE;
269  }
270  break;
271  case ROUNDNEAREST:
272  if (src_exponent == -1 &&
273  Sgl_isnotzero_mantissa(src)) {
274  if (Sgl_isone_sign(src)) {
275  resultp1 = 0;
276  resultp2 = 0;
277  if (Is_invalidtrap_enabled()) {
278  return(INVALIDEXCEPTION);
279  }
280  Set_invalidflag();
281  inexact = FALSE;
282  }
283  else Duint_increment(resultp1,resultp2);
284  }
285  }
286  }
287  }
288  Duint_copytoptr(resultp1,resultp2,dstptr);
289  if (inexact) {
291  else Set_inexactflag();
292  }
293  return(NOEXCEPTION);
294 }
295 
296 /*
297  * Double Floating-point to Single Unsigned Fixed
298  */
299 /*ARGSUSED*/
300 int
301 dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
302  unsigned int *dstptr, unsigned int *status)
303 {
304  register unsigned int srcp1, srcp2, result;
305  register int src_exponent;
306  register boolean inexact = FALSE;
307 
308  Dbl_copyfromptr(srcptr,srcp1,srcp2);
309  src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
310 
311  /*
312  * Test for overflow
313  */
314  if (src_exponent > SGL_FX_MAX_EXP + 1) {
315  if (Dbl_isone_sign(srcp1)) {
316  result = 0;
317  } else {
318  result = 0xffffffff;
319  }
320  if (Is_invalidtrap_enabled()) {
321  return(INVALIDEXCEPTION);
322  }
323  Set_invalidflag();
324  *dstptr = result;
325  return(NOEXCEPTION);
326  }
327  /*
328  * Generate result
329  */
330  if (src_exponent >= 0) {
331  /*
332  * Check sign.
333  * If negative, trap unimplemented.
334  */
335  if (Dbl_isone_sign(srcp1)) {
336  result = 0;
337  if (Is_invalidtrap_enabled()) {
338  return(INVALIDEXCEPTION);
339  }
340  Set_invalidflag();
341  *dstptr = result;
342  return(NOEXCEPTION);
343  }
345  Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
346 
347  /* check for inexact */
348  if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
349  inexact = TRUE;
350  /* round result */
351  switch (Rounding_mode()) {
352  case ROUNDPLUS:
353  result++;
354  break;
355  case ROUNDMINUS: /* never negative */
356  break;
357  case ROUNDNEAREST:
358  if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
359  (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
360  result&1))
361  result++;
362  break;
363  }
364  /* check for overflow */
365  if (result == 0) {
366  result = 0xffffffff;
367  if (Is_invalidtrap_enabled()) {
368  return(INVALIDEXCEPTION);
369  }
370  Set_invalidflag();
371  *dstptr = result;
372  return(NOEXCEPTION);
373  }
374  }
375  } else {
376  result = 0;
377 
378  /* check for inexact */
379  if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
380  inexact = TRUE;
381  /* round result */
382  switch (Rounding_mode()) {
383  case ROUNDPLUS:
384  if (Dbl_iszero_sign(srcp1)) result++;
385  break;
386  case ROUNDMINUS:
387  if (Dbl_isone_sign(srcp1)) {
388  result = 0;
389  if (Is_invalidtrap_enabled()) {
390  return(INVALIDEXCEPTION);
391  }
392  Set_invalidflag();
393  inexact = FALSE;
394  }
395  break;
396  case ROUNDNEAREST:
397  if (src_exponent == -1 &&
398  Dbl_isnotzero_mantissa(srcp1,srcp2))
399  if (Dbl_isone_sign(srcp1)) {
400  result = 0;
401  if (Is_invalidtrap_enabled()) {
402  return(INVALIDEXCEPTION);
403  }
404  Set_invalidflag();
405  inexact = FALSE;
406  }
407  else result++;
408  }
409  }
410  }
411  *dstptr = result;
412  if (inexact) {
414  else Set_inexactflag();
415  }
416  return(NOEXCEPTION);
417 }
418 
419 /*
420  * Double Floating-point to Double Unsigned Fixed
421  */
422 /*ARGSUSED*/
423 int
424 dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
425  dbl_unsigned * dstptr, unsigned int *status)
426 {
427  register int src_exponent;
428  register unsigned int srcp1, srcp2, resultp1, resultp2;
429  register boolean inexact = FALSE;
430 
431  Dbl_copyfromptr(srcptr,srcp1,srcp2);
432  src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
433 
434  /*
435  * Test for overflow
436  */
437  if (src_exponent > DBL_FX_MAX_EXP + 1) {
438  if (Dbl_isone_sign(srcp1)) {
439  resultp1 = resultp2 = 0;
440  } else {
441  resultp1 = resultp2 = 0xffffffff;
442  }
443  if (Is_invalidtrap_enabled()) {
444  return(INVALIDEXCEPTION);
445  }
446  Set_invalidflag();
447  Duint_copytoptr(resultp1,resultp2,dstptr);
448  return(NOEXCEPTION);
449  }
450 
451  /*
452  * Generate result
453  */
454  if (src_exponent >= 0) {
455  /*
456  * Check sign.
457  * If negative, trap unimplemented.
458  */
459  if (Dbl_isone_sign(srcp1)) {
460  resultp1 = resultp2 = 0;
461  if (Is_invalidtrap_enabled()) {
462  return(INVALIDEXCEPTION);
463  }
464  Set_invalidflag();
465  Duint_copytoptr(resultp1,resultp2,dstptr);
466  return(NOEXCEPTION);
467  }
469  Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
470  resultp2);
471 
472  /* check for inexact */
473  if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
474  inexact = TRUE;
475  /* round result */
476  switch (Rounding_mode()) {
477  case ROUNDPLUS:
478  Duint_increment(resultp1,resultp2);
479  break;
480  case ROUNDMINUS: /* never negative */
481  break;
482  case ROUNDNEAREST:
483  if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
484  if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
485  Duint_isone_lowp2(resultp2))
486  Duint_increment(resultp1,resultp2);
487  }
488  }
489  } else {
490  Duint_setzero(resultp1,resultp2);
491 
492  /* check for inexact */
493  if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
494  inexact = TRUE;
495  /* round result */
496  switch (Rounding_mode()) {
497  case ROUNDPLUS:
498  if (Dbl_iszero_sign(srcp1)) {
499  Duint_increment(resultp1,resultp2);
500  }
501  break;
502  case ROUNDMINUS:
503  if (Dbl_isone_sign(srcp1)) {
504  resultp1 = resultp2 = 0;
505  if (Is_invalidtrap_enabled()) {
506  return(INVALIDEXCEPTION);
507  }
508  Set_invalidflag();
509  inexact = FALSE;
510  }
511  break;
512  case ROUNDNEAREST:
513  if (src_exponent == -1 &&
514  Dbl_isnotzero_mantissa(srcp1,srcp2))
515  if (Dbl_iszero_sign(srcp1)) {
516  Duint_increment(resultp1,resultp2);
517  } else {
518  resultp1 = 0;
519  resultp2 = 0;
520  if (Is_invalidtrap_enabled()) {
521  return(INVALIDEXCEPTION);
522  }
523  Set_invalidflag();
524  inexact = FALSE;
525  }
526  }
527  }
528  }
529  Duint_copytoptr(resultp1,resultp2,dstptr);
530  if (inexact) {
532  else Set_inexactflag();
533  }
534  return(NOEXCEPTION);
535 }
536