Linux 2.6.25-rc4
[linux-2.6/next.git] / arch / parisc / math-emu / fcnvfx.c
blobd6475bddb507dc95a17f8d8800c535078abf53da
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/fcnvfx.c $Revision: 1.1 $
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
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)
39 * Internal Interfaces:
41 * Theory:
42 * <<please update with a overview of the operation of this file>>
44 * END_DESC
48 #include "float.h"
49 #include "sgl_float.h"
50 #include "dbl_float.h"
51 #include "cnv_float.h"
54 * Single Floating-point to Single Fixed-point
56 /*ARGSUSED*/
57 int
58 sgl_to_sgl_fcnvfx(
59 sgl_floating_point *srcptr,
60 sgl_floating_point *nullptr,
61 int *dstptr,
62 sgl_floating_point *status)
64 register unsigned int src, temp;
65 register int src_exponent, result;
66 register boolean inexact = FALSE;
68 src = *srcptr;
69 src_exponent = Sgl_exponent(src) - SGL_BIAS;
71 /*
72 * Test for overflow
74 if (src_exponent > SGL_FX_MAX_EXP) {
75 /* check for MININT */
76 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
77 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
78 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
79 else result = 0x80000000;
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
90 * Generate result
92 if (src_exponent >= 0) {
93 temp = src;
94 Sgl_clear_signexponent_set_hidden(temp);
95 Int_from_sgl_mantissa(temp,src_exponent);
96 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
97 else result = Sgl_all(temp);
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--;
120 else {
121 result = 0;
123 /* check for inexact */
124 if (Sgl_isnotzero_exponentmantissa(src)) {
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--;
142 *dstptr = result;
143 if (inexact) {
144 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
145 else Set_inexactflag();
147 return(NOEXCEPTION);
151 * Single Floating-point to Double Fixed-point
153 /*ARGSUSED*/
155 sgl_to_dbl_fcnvfx(
156 sgl_floating_point *srcptr,
157 unsigned int *nullptr,
158 dbl_integer *dstptr,
159 unsigned int *status)
161 register int src_exponent, resultp1;
162 register unsigned int src, temp, resultp2;
163 register boolean inexact = FALSE;
165 src = *srcptr;
166 src_exponent = Sgl_exponent(src) - SGL_BIAS;
169 * Test for overflow
171 if (src_exponent > DBL_FX_MAX_EXP) {
172 /* check for MININT */
173 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
174 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
175 if (Sgl_iszero_sign(src)) {
176 resultp1 = 0x7fffffff;
177 resultp2 = 0xffffffff;
179 else {
180 resultp1 = 0x80000000;
181 resultp2 = 0;
183 if (Is_invalidtrap_enabled()) {
184 return(INVALIDEXCEPTION);
186 Set_invalidflag();
187 Dint_copytoptr(resultp1,resultp2,dstptr);
188 return(NOEXCEPTION);
190 Dint_set_minint(resultp1,resultp2);
191 Dint_copytoptr(resultp1,resultp2,dstptr);
192 return(NOEXCEPTION);
195 * Generate result
197 if (src_exponent >= 0) {
198 temp = src;
199 Sgl_clear_signexponent_set_hidden(temp);
200 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
201 if (Sgl_isone_sign(src)) {
202 Dint_setone_sign(resultp1,resultp2);
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);
214 break;
215 case ROUNDMINUS:
216 if (Sgl_isone_sign(src)) {
217 Dint_decrement(resultp1,resultp2);
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);
227 else {
228 Dint_decrement(resultp1,resultp2);
233 else {
234 Dint_setzero(resultp1,resultp2);
236 /* check for inexact */
237 if (Sgl_isnotzero_exponentmantissa(src)) {
238 inexact = TRUE;
239 /* round result */
240 switch (Rounding_mode()) {
241 case ROUNDPLUS:
242 if (Sgl_iszero_sign(src)) {
243 Dint_increment(resultp1,resultp2);
245 break;
246 case ROUNDMINUS:
247 if (Sgl_isone_sign(src)) {
248 Dint_decrement(resultp1,resultp2);
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);
257 else {
258 Dint_decrement(resultp1,resultp2);
263 Dint_copytoptr(resultp1,resultp2,dstptr);
264 if (inexact) {
265 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
266 else Set_inexactflag();
268 return(NOEXCEPTION);
272 * Double Floating-point to Single Fixed-point
274 /*ARGSUSED*/
276 dbl_to_sgl_fcnvfx(
277 dbl_floating_point *srcptr,
278 unsigned int *nullptr,
279 int *dstptr,
280 unsigned int *status)
282 register unsigned int srcp1,srcp2, tempp1,tempp2;
283 register int src_exponent, result;
284 register boolean inexact = FALSE;
286 Dbl_copyfromptr(srcptr,srcp1,srcp2);
287 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
290 * Test for overflow
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;
298 if (Is_invalidtrap_enabled()) {
299 return(INVALIDEXCEPTION);
301 Set_invalidflag();
302 *dstptr = result;
303 return(NOEXCEPTION);
307 * Generate result
309 if (src_exponent >= 0) {
310 tempp1 = srcp1;
311 tempp2 = srcp2;
312 Dbl_clear_signexponent_set_hidden(tempp1);
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);
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--;
336 /* check for overflow */
337 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
338 (Dbl_isone_sign(srcp1) && result > 0)) {
340 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
341 else result = 0x80000000;
343 if (Is_invalidtrap_enabled()) {
344 return(INVALIDEXCEPTION);
346 Set_invalidflag();
347 *dstptr = result;
348 return(NOEXCEPTION);
352 else {
353 result = 0;
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--;
374 *dstptr = result;
375 if (inexact) {
376 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
377 else Set_inexactflag();
379 return(NOEXCEPTION);
383 * Double Floating-point to Double Fixed-point
385 /*ARGSUSED*/
387 dbl_to_dbl_fcnvfx(
388 dbl_floating_point *srcptr,
389 unsigned int *nullptr,
390 dbl_integer *dstptr,
391 unsigned int *status)
393 register int src_exponent, resultp1;
394 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
395 register boolean inexact = FALSE;
397 Dbl_copyfromptr(srcptr,srcp1,srcp2);
398 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
401 * Test for overflow
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;
411 else {
412 resultp1 = 0x80000000;
413 resultp2 = 0;
415 if (Is_invalidtrap_enabled()) {
416 return(INVALIDEXCEPTION);
418 Set_invalidflag();
419 Dint_copytoptr(resultp1,resultp2,dstptr);
420 return(NOEXCEPTION);
425 * Generate result
427 if (src_exponent >= 0) {
428 tempp1 = srcp1;
429 tempp2 = srcp2;
430 Dbl_clear_signexponent_set_hidden(tempp1);
431 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
432 resultp2);
433 if (Dbl_isone_sign(srcp1)) {
434 Dint_setone_sign(resultp1,resultp2);
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);
446 break;
447 case ROUNDMINUS:
448 if (Dbl_isone_sign(srcp1)) {
449 Dint_decrement(resultp1,resultp2);
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);
459 else {
460 Dint_decrement(resultp1,resultp2);
465 else {
466 Dint_setzero(resultp1,resultp2);
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);
477 break;
478 case ROUNDMINUS:
479 if (Dbl_isone_sign(srcp1)) {
480 Dint_decrement(resultp1,resultp2);
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);
489 else {
490 Dint_decrement(resultp1,resultp2);
495 Dint_copytoptr(resultp1,resultp2,dstptr);
496 if (inexact) {
497 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
498 else Set_inexactflag();
500 return(NOEXCEPTION);