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)
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
25 * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
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:
42 * <<please update with a overview of the operation of this file>>
49 #include "sgl_float.h"
50 #include "dbl_float.h"
51 #include "cnv_float.h"
54 * Single Floating-point to Single Fixed-point
59 sgl_floating_point *srcptr,
60 sgl_floating_point *nullptr,
62 sgl_floating_point *status)
64 register unsigned int src, temp;
65 register int src_exponent, result;
66 register boolean inexact = FALSE;
69 src_exponent = Sgl_exponent(src) - SGL_BIAS;
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);
92 if (src_exponent >= 0) {
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)) {
103 switch (Rounding_mode()) {
105 if (Sgl_iszero_sign(src)) result++;
108 if (Sgl_isone_sign(src)) result--;
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++;
123 /* check for inexact */
124 if (Sgl_isnotzero_exponentmantissa(src)) {
127 switch (Rounding_mode()) {
129 if (Sgl_iszero_sign(src)) result++;
132 if (Sgl_isone_sign(src)) result--;
135 if (src_exponent == -1)
136 if (Sgl_isnotzero_mantissa(src))
137 if (Sgl_iszero_sign(src)) result++;
144 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
145 else Set_inexactflag();
151 * Single Floating-point to Double Fixed-point
156 sgl_floating_point *srcptr,
157 unsigned int *nullptr,
159 unsigned int *status)
161 register int src_exponent, resultp1;
162 register unsigned int src, temp, resultp2;
163 register boolean inexact = FALSE;
166 src_exponent = Sgl_exponent(src) - SGL_BIAS;
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;
180 resultp1 = 0x80000000;
183 if (Is_invalidtrap_enabled()) {
184 return(INVALIDEXCEPTION);
187 Dint_copytoptr(resultp1,resultp2,dstptr);
190 Dint_set_minint(resultp1,resultp2);
191 Dint_copytoptr(resultp1,resultp2,dstptr);
197 if (src_exponent >= 0) {
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)) {
209 switch (Rounding_mode()) {
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
216 if (Sgl_isone_sign(src)) {
217 Dint_decrement(resultp1,resultp2);
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);
228 Dint_decrement(resultp1,resultp2);
234 Dint_setzero(resultp1,resultp2);
236 /* check for inexact */
237 if (Sgl_isnotzero_exponentmantissa(src)) {
240 switch (Rounding_mode()) {
242 if (Sgl_iszero_sign(src)) {
243 Dint_increment(resultp1,resultp2);
247 if (Sgl_isone_sign(src)) {
248 Dint_decrement(resultp1,resultp2);
252 if (src_exponent == -1)
253 if (Sgl_isnotzero_mantissa(src))
254 if (Sgl_iszero_sign(src)) {
255 Dint_increment(resultp1,resultp2);
258 Dint_decrement(resultp1,resultp2);
263 Dint_copytoptr(resultp1,resultp2,dstptr);
265 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
266 else Set_inexactflag();
272 * Double Floating-point to Single Fixed-point
277 dbl_floating_point *srcptr,
278 unsigned int *nullptr,
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;
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);
309 if (src_exponent >= 0) {
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)) {
322 switch (Rounding_mode()) {
324 if (Dbl_iszero_sign(srcp1)) result++;
327 if (Dbl_isone_sign(srcp1)) result--;
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++;
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);
355 /* check for inexact */
356 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
359 switch (Rounding_mode()) {
361 if (Dbl_iszero_sign(srcp1)) result++;
364 if (Dbl_isone_sign(srcp1)) result--;
367 if (src_exponent == -1)
368 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
369 if (Dbl_iszero_sign(srcp1)) result++;
376 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
377 else Set_inexactflag();
383 * Double Floating-point to Double Fixed-point
388 dbl_floating_point *srcptr,
389 unsigned int *nullptr,
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;
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;
412 resultp1 = 0x80000000;
415 if (Is_invalidtrap_enabled()) {
416 return(INVALIDEXCEPTION);
419 Dint_copytoptr(resultp1,resultp2,dstptr);
427 if (src_exponent >= 0) {
430 Dbl_clear_signexponent_set_hidden(tempp1);
431 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
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)) {
441 switch (Rounding_mode()) {
443 if (Dbl_iszero_sign(srcp1)) {
444 Dint_increment(resultp1,resultp2);
448 if (Dbl_isone_sign(srcp1)) {
449 Dint_decrement(resultp1,resultp2);
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);
460 Dint_decrement(resultp1,resultp2);
466 Dint_setzero(resultp1,resultp2);
468 /* check for inexact */
469 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
472 switch (Rounding_mode()) {
474 if (Dbl_iszero_sign(srcp1)) {
475 Dint_increment(resultp1,resultp2);
479 if (Dbl_isone_sign(srcp1)) {
480 Dint_decrement(resultp1,resultp2);
484 if (src_exponent == -1)
485 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
486 if (Dbl_iszero_sign(srcp1)) {
487 Dint_increment(resultp1,resultp2);
490 Dint_decrement(resultp1,resultp2);
495 Dint_copytoptr(resultp1,resultp2,dstptr);
497 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
498 else Set_inexactflag();