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