Linux 2.6.25-rc4
[linux-2.6/next.git] / arch / parisc / math-emu / fcnvfu.c
blob7e8565537bf555f689a418ef262b7b7463fcf9ab
1 /*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4 * Floating-point emulation code
5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
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.
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.
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
22 * BEGIN_DESC
24 * File:
25 * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $
27 * Purpose:
28 * Floating-point to Unsigned Fixed-point Converts
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)
36 * Internal Interfaces:
38 * Theory:
39 * <<please update with a overview of the operation of this file>>
41 * END_DESC
45 #include "float.h"
46 #include "sgl_float.h"
47 #include "dbl_float.h"
48 #include "cnv_float.h"
50 /************************************************************************
51 * Floating-point to Unsigned Fixed-point Converts *
52 ************************************************************************/
55 * Single Floating-point to Single Unsigned Fixed
57 /*ARGSUSED*/
58 int
59 sgl_to_sgl_fcnvfu(
60 sgl_floating_point *srcptr,
61 unsigned int *nullptr,
62 unsigned int *dstptr,
63 unsigned int *status)
65 register unsigned int src, result;
66 register int src_exponent;
67 register boolean inexact = FALSE;
69 src = *srcptr;
70 src_exponent = Sgl_exponent(src) - SGL_BIAS;
72 /*
73 * Test for overflow
75 if (src_exponent > SGL_FX_MAX_EXP + 1) {
76 if (Sgl_isone_sign(src)) {
77 result = 0;
78 } else {
79 result = 0xffffffff;
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
89 * Generate result
91 if (src_exponent >= 0) {
92 /*
93 * Check sign.
94 * If negative, trap unimplemented.
96 if (Sgl_isone_sign(src)) {
97 result = 0;
98 if (Is_invalidtrap_enabled()) {
99 return(INVALIDEXCEPTION);
101 Set_invalidflag();
102 *dstptr = result;
103 return(NOEXCEPTION);
105 Sgl_clear_signexponent_set_hidden(src);
106 Suint_from_sgl_mantissa(src,src_exponent,result);
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++;
124 break;
127 } else {
128 result = 0;
130 /* check for inexact */
131 if (Sgl_isnotzero_exponentmantissa(src)) {
132 inexact = TRUE;
133 /* round result */
134 switch (Rounding_mode()) {
135 case ROUNDPLUS:
136 if (Sgl_iszero_sign(src)) {
137 result++;
139 break;
140 case ROUNDMINUS:
141 if (Sgl_isone_sign(src)) {
142 result = 0;
143 if (Is_invalidtrap_enabled()) {
144 return(INVALIDEXCEPTION);
146 Set_invalidflag();
147 inexact = FALSE;
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);
158 Set_invalidflag();
159 inexact = FALSE;
161 else result++;
163 break;
167 *dstptr = result;
168 if (inexact) {
169 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
170 else Set_inexactflag();
172 return(NOEXCEPTION);
176 * Single Floating-point to Double Unsigned Fixed
178 /*ARGSUSED*/
180 sgl_to_dbl_fcnvfu(
181 sgl_floating_point *srcptr,
182 unsigned int *nullptr,
183 dbl_unsigned *dstptr,
184 unsigned int *status)
186 register int src_exponent;
187 register unsigned int src, resultp1, resultp2;
188 register boolean inexact = FALSE;
190 src = *srcptr;
191 src_exponent = Sgl_exponent(src) - SGL_BIAS;
194 * Test for overflow
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;
202 if (Is_invalidtrap_enabled()) {
203 return(INVALIDEXCEPTION);
205 Set_invalidflag();
206 Duint_copytoptr(resultp1,resultp2,dstptr);
207 return(NOEXCEPTION);
210 * Generate result
212 if (src_exponent >= 0) {
214 * Check sign.
215 * If negative, trap unimplemented.
217 if (Sgl_isone_sign(src)) {
218 resultp1 = resultp2 = 0;
219 if (Is_invalidtrap_enabled()) {
220 return(INVALIDEXCEPTION);
222 Set_invalidflag();
223 Duint_copytoptr(resultp1,resultp2,dstptr);
224 return(NOEXCEPTION);
226 Sgl_clear_signexponent_set_hidden(src);
227 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
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);
245 break;
248 } else {
249 Duint_setzero(resultp1,resultp2);
251 /* check for inexact */
252 if (Sgl_isnotzero_exponentmantissa(src)) {
253 inexact = TRUE;
254 /* round result */
255 switch (Rounding_mode()) {
256 case ROUNDPLUS:
257 if (Sgl_iszero_sign(src)) {
258 Duint_increment(resultp1,resultp2);
260 break;
261 case ROUNDMINUS:
262 if (Sgl_isone_sign(src)) {
263 resultp1 = resultp2 = 0;
264 if (Is_invalidtrap_enabled()) {
265 return(INVALIDEXCEPTION);
267 Set_invalidflag();
268 inexact = FALSE;
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);
280 Set_invalidflag();
281 inexact = FALSE;
283 else Duint_increment(resultp1,resultp2);
288 Duint_copytoptr(resultp1,resultp2,dstptr);
289 if (inexact) {
290 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
291 else Set_inexactflag();
293 return(NOEXCEPTION);
297 * Double Floating-point to Single Unsigned Fixed
299 /*ARGSUSED*/
301 dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
302 unsigned int *dstptr, unsigned int *status)
304 register unsigned int srcp1, srcp2, result;
305 register int src_exponent;
306 register boolean inexact = FALSE;
308 Dbl_copyfromptr(srcptr,srcp1,srcp2);
309 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
312 * Test for overflow
314 if (src_exponent > SGL_FX_MAX_EXP + 1) {
315 if (Dbl_isone_sign(srcp1)) {
316 result = 0;
317 } else {
318 result = 0xffffffff;
320 if (Is_invalidtrap_enabled()) {
321 return(INVALIDEXCEPTION);
323 Set_invalidflag();
324 *dstptr = result;
325 return(NOEXCEPTION);
328 * Generate result
330 if (src_exponent >= 0) {
332 * Check sign.
333 * If negative, trap unimplemented.
335 if (Dbl_isone_sign(srcp1)) {
336 result = 0;
337 if (Is_invalidtrap_enabled()) {
338 return(INVALIDEXCEPTION);
340 Set_invalidflag();
341 *dstptr = result;
342 return(NOEXCEPTION);
344 Dbl_clear_signexponent_set_hidden(srcp1);
345 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
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;
364 /* check for overflow */
365 if (result == 0) {
366 result = 0xffffffff;
367 if (Is_invalidtrap_enabled()) {
368 return(INVALIDEXCEPTION);
370 Set_invalidflag();
371 *dstptr = result;
372 return(NOEXCEPTION);
375 } else {
376 result = 0;
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);
392 Set_invalidflag();
393 inexact = FALSE;
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);
404 Set_invalidflag();
405 inexact = FALSE;
407 else result++;
411 *dstptr = result;
412 if (inexact) {
413 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
414 else Set_inexactflag();
416 return(NOEXCEPTION);
420 * Double Floating-point to Double Unsigned Fixed
422 /*ARGSUSED*/
424 dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
425 dbl_unsigned * dstptr, unsigned int *status)
427 register int src_exponent;
428 register unsigned int srcp1, srcp2, resultp1, resultp2;
429 register boolean inexact = FALSE;
431 Dbl_copyfromptr(srcptr,srcp1,srcp2);
432 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
435 * Test for overflow
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;
443 if (Is_invalidtrap_enabled()) {
444 return(INVALIDEXCEPTION);
446 Set_invalidflag();
447 Duint_copytoptr(resultp1,resultp2,dstptr);
448 return(NOEXCEPTION);
452 * Generate result
454 if (src_exponent >= 0) {
456 * Check sign.
457 * If negative, trap unimplemented.
459 if (Dbl_isone_sign(srcp1)) {
460 resultp1 = resultp2 = 0;
461 if (Is_invalidtrap_enabled()) {
462 return(INVALIDEXCEPTION);
464 Set_invalidflag();
465 Duint_copytoptr(resultp1,resultp2,dstptr);
466 return(NOEXCEPTION);
468 Dbl_clear_signexponent_set_hidden(srcp1);
469 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
470 resultp2);
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);
489 } else {
490 Duint_setzero(resultp1,resultp2);
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);
501 break;
502 case ROUNDMINUS:
503 if (Dbl_isone_sign(srcp1)) {
504 resultp1 = resultp2 = 0;
505 if (Is_invalidtrap_enabled()) {
506 return(INVALIDEXCEPTION);
508 Set_invalidflag();
509 inexact = FALSE;
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);
523 Set_invalidflag();
524 inexact = FALSE;
529 Duint_copytoptr(resultp1,resultp2,dstptr);
530 if (inexact) {
531 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
532 else Set_inexactflag();
534 return(NOEXCEPTION);