WIP FPC-III support
[linux/fpc-iii.git] / arch / parisc / math-emu / fcnvfx.c
blob5e153078d8035a3d4c13ae0e5b961bd897f7bc31
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
5 * Floating-point emulation code
6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7 */
8 /*
9 * BEGIN_DESC
11 * File:
12 * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $
14 * Purpose:
15 * Single Floating-point to Single Fixed-point
16 * Single Floating-point to Double Fixed-point
17 * Double Floating-point to Single Fixed-point
18 * Double Floating-point to Double Fixed-point
20 * External Interfaces:
21 * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
22 * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
23 * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
24 * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
26 * Internal Interfaces:
28 * Theory:
29 * <<please update with a overview of the operation of this file>>
31 * END_DESC
35 #include "float.h"
36 #include "sgl_float.h"
37 #include "dbl_float.h"
38 #include "cnv_float.h"
41 * Single Floating-point to Single Fixed-point
43 /*ARGSUSED*/
44 int
45 sgl_to_sgl_fcnvfx(
46 sgl_floating_point *srcptr,
47 sgl_floating_point *nullptr,
48 int *dstptr,
49 sgl_floating_point *status)
51 register unsigned int src, temp;
52 register int src_exponent, result;
53 register boolean inexact = FALSE;
55 src = *srcptr;
56 src_exponent = Sgl_exponent(src) - SGL_BIAS;
58 /*
59 * Test for overflow
61 if (src_exponent > SGL_FX_MAX_EXP) {
62 /* check for MININT */
63 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
64 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
65 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
66 else result = 0x80000000;
68 if (Is_invalidtrap_enabled()) {
69 return(INVALIDEXCEPTION);
71 Set_invalidflag();
72 *dstptr = result;
73 return(NOEXCEPTION);
77 * Generate result
79 if (src_exponent >= 0) {
80 temp = src;
81 Sgl_clear_signexponent_set_hidden(temp);
82 Int_from_sgl_mantissa(temp,src_exponent);
83 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
84 else result = Sgl_all(temp);
86 /* check for inexact */
87 if (Sgl_isinexact_to_fix(src,src_exponent)) {
88 inexact = TRUE;
89 /* round result */
90 switch (Rounding_mode()) {
91 case ROUNDPLUS:
92 if (Sgl_iszero_sign(src)) result++;
93 break;
94 case ROUNDMINUS:
95 if (Sgl_isone_sign(src)) result--;
96 break;
97 case ROUNDNEAREST:
98 if (Sgl_isone_roundbit(src,src_exponent)) {
99 if (Sgl_isone_stickybit(src,src_exponent)
100 || (Sgl_isone_lowmantissa(temp)))
101 if (Sgl_iszero_sign(src)) result++;
102 else result--;
107 else {
108 result = 0;
110 /* check for inexact */
111 if (Sgl_isnotzero_exponentmantissa(src)) {
112 inexact = TRUE;
113 /* round result */
114 switch (Rounding_mode()) {
115 case ROUNDPLUS:
116 if (Sgl_iszero_sign(src)) result++;
117 break;
118 case ROUNDMINUS:
119 if (Sgl_isone_sign(src)) result--;
120 break;
121 case ROUNDNEAREST:
122 if (src_exponent == -1)
123 if (Sgl_isnotzero_mantissa(src))
124 if (Sgl_iszero_sign(src)) result++;
125 else result--;
129 *dstptr = result;
130 if (inexact) {
131 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
132 else Set_inexactflag();
134 return(NOEXCEPTION);
138 * Single Floating-point to Double Fixed-point
140 /*ARGSUSED*/
142 sgl_to_dbl_fcnvfx(
143 sgl_floating_point *srcptr,
144 unsigned int *nullptr,
145 dbl_integer *dstptr,
146 unsigned int *status)
148 register int src_exponent, resultp1;
149 register unsigned int src, temp, resultp2;
150 register boolean inexact = FALSE;
152 src = *srcptr;
153 src_exponent = Sgl_exponent(src) - SGL_BIAS;
156 * Test for overflow
158 if (src_exponent > DBL_FX_MAX_EXP) {
159 /* check for MININT */
160 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
161 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
162 if (Sgl_iszero_sign(src)) {
163 resultp1 = 0x7fffffff;
164 resultp2 = 0xffffffff;
166 else {
167 resultp1 = 0x80000000;
168 resultp2 = 0;
170 if (Is_invalidtrap_enabled()) {
171 return(INVALIDEXCEPTION);
173 Set_invalidflag();
174 Dint_copytoptr(resultp1,resultp2,dstptr);
175 return(NOEXCEPTION);
177 Dint_set_minint(resultp1,resultp2);
178 Dint_copytoptr(resultp1,resultp2,dstptr);
179 return(NOEXCEPTION);
182 * Generate result
184 if (src_exponent >= 0) {
185 temp = src;
186 Sgl_clear_signexponent_set_hidden(temp);
187 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
188 if (Sgl_isone_sign(src)) {
189 Dint_setone_sign(resultp1,resultp2);
192 /* check for inexact */
193 if (Sgl_isinexact_to_fix(src,src_exponent)) {
194 inexact = TRUE;
195 /* round result */
196 switch (Rounding_mode()) {
197 case ROUNDPLUS:
198 if (Sgl_iszero_sign(src)) {
199 Dint_increment(resultp1,resultp2);
201 break;
202 case ROUNDMINUS:
203 if (Sgl_isone_sign(src)) {
204 Dint_decrement(resultp1,resultp2);
206 break;
207 case ROUNDNEAREST:
208 if (Sgl_isone_roundbit(src,src_exponent))
209 if (Sgl_isone_stickybit(src,src_exponent) ||
210 (Dint_isone_lowp2(resultp2)))
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
214 else {
215 Dint_decrement(resultp1,resultp2);
220 else {
221 Dint_setzero(resultp1,resultp2);
223 /* check for inexact */
224 if (Sgl_isnotzero_exponentmantissa(src)) {
225 inexact = TRUE;
226 /* round result */
227 switch (Rounding_mode()) {
228 case ROUNDPLUS:
229 if (Sgl_iszero_sign(src)) {
230 Dint_increment(resultp1,resultp2);
232 break;
233 case ROUNDMINUS:
234 if (Sgl_isone_sign(src)) {
235 Dint_decrement(resultp1,resultp2);
237 break;
238 case ROUNDNEAREST:
239 if (src_exponent == -1)
240 if (Sgl_isnotzero_mantissa(src))
241 if (Sgl_iszero_sign(src)) {
242 Dint_increment(resultp1,resultp2);
244 else {
245 Dint_decrement(resultp1,resultp2);
250 Dint_copytoptr(resultp1,resultp2,dstptr);
251 if (inexact) {
252 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
253 else Set_inexactflag();
255 return(NOEXCEPTION);
259 * Double Floating-point to Single Fixed-point
261 /*ARGSUSED*/
263 dbl_to_sgl_fcnvfx(
264 dbl_floating_point *srcptr,
265 unsigned int *nullptr,
266 int *dstptr,
267 unsigned int *status)
269 register unsigned int srcp1,srcp2, tempp1,tempp2;
270 register int src_exponent, result;
271 register boolean inexact = FALSE;
273 Dbl_copyfromptr(srcptr,srcp1,srcp2);
274 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
277 * Test for overflow
279 if (src_exponent > SGL_FX_MAX_EXP) {
280 /* check for MININT */
281 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
282 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
283 else result = 0x80000000;
285 if (Is_invalidtrap_enabled()) {
286 return(INVALIDEXCEPTION);
288 Set_invalidflag();
289 *dstptr = result;
290 return(NOEXCEPTION);
294 * Generate result
296 if (src_exponent >= 0) {
297 tempp1 = srcp1;
298 tempp2 = srcp2;
299 Dbl_clear_signexponent_set_hidden(tempp1);
300 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
301 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
302 result = -Dbl_allp1(tempp1);
303 else result = Dbl_allp1(tempp1);
305 /* check for inexact */
306 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
307 inexact = TRUE;
308 /* round result */
309 switch (Rounding_mode()) {
310 case ROUNDPLUS:
311 if (Dbl_iszero_sign(srcp1)) result++;
312 break;
313 case ROUNDMINUS:
314 if (Dbl_isone_sign(srcp1)) result--;
315 break;
316 case ROUNDNEAREST:
317 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
318 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
319 (Dbl_isone_lowmantissap1(tempp1)))
320 if (Dbl_iszero_sign(srcp1)) result++;
321 else result--;
323 /* check for overflow */
324 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
325 (Dbl_isone_sign(srcp1) && result > 0)) {
327 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
328 else result = 0x80000000;
330 if (Is_invalidtrap_enabled()) {
331 return(INVALIDEXCEPTION);
333 Set_invalidflag();
334 *dstptr = result;
335 return(NOEXCEPTION);
339 else {
340 result = 0;
342 /* check for inexact */
343 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
344 inexact = TRUE;
345 /* round result */
346 switch (Rounding_mode()) {
347 case ROUNDPLUS:
348 if (Dbl_iszero_sign(srcp1)) result++;
349 break;
350 case ROUNDMINUS:
351 if (Dbl_isone_sign(srcp1)) result--;
352 break;
353 case ROUNDNEAREST:
354 if (src_exponent == -1)
355 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
356 if (Dbl_iszero_sign(srcp1)) result++;
357 else result--;
361 *dstptr = result;
362 if (inexact) {
363 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
364 else Set_inexactflag();
366 return(NOEXCEPTION);
370 * Double Floating-point to Double Fixed-point
372 /*ARGSUSED*/
374 dbl_to_dbl_fcnvfx(
375 dbl_floating_point *srcptr,
376 unsigned int *nullptr,
377 dbl_integer *dstptr,
378 unsigned int *status)
380 register int src_exponent, resultp1;
381 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
382 register boolean inexact = FALSE;
384 Dbl_copyfromptr(srcptr,srcp1,srcp2);
385 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
388 * Test for overflow
390 if (src_exponent > DBL_FX_MAX_EXP) {
391 /* check for MININT */
392 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
393 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
394 if (Dbl_iszero_sign(srcp1)) {
395 resultp1 = 0x7fffffff;
396 resultp2 = 0xffffffff;
398 else {
399 resultp1 = 0x80000000;
400 resultp2 = 0;
402 if (Is_invalidtrap_enabled()) {
403 return(INVALIDEXCEPTION);
405 Set_invalidflag();
406 Dint_copytoptr(resultp1,resultp2,dstptr);
407 return(NOEXCEPTION);
412 * Generate result
414 if (src_exponent >= 0) {
415 tempp1 = srcp1;
416 tempp2 = srcp2;
417 Dbl_clear_signexponent_set_hidden(tempp1);
418 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
419 resultp2);
420 if (Dbl_isone_sign(srcp1)) {
421 Dint_setone_sign(resultp1,resultp2);
424 /* check for inexact */
425 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
426 inexact = TRUE;
427 /* round result */
428 switch (Rounding_mode()) {
429 case ROUNDPLUS:
430 if (Dbl_iszero_sign(srcp1)) {
431 Dint_increment(resultp1,resultp2);
433 break;
434 case ROUNDMINUS:
435 if (Dbl_isone_sign(srcp1)) {
436 Dint_decrement(resultp1,resultp2);
438 break;
439 case ROUNDNEAREST:
440 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
441 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
442 (Dint_isone_lowp2(resultp2)))
443 if (Dbl_iszero_sign(srcp1)) {
444 Dint_increment(resultp1,resultp2);
446 else {
447 Dint_decrement(resultp1,resultp2);
452 else {
453 Dint_setzero(resultp1,resultp2);
455 /* check for inexact */
456 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
457 inexact = TRUE;
458 /* round result */
459 switch (Rounding_mode()) {
460 case ROUNDPLUS:
461 if (Dbl_iszero_sign(srcp1)) {
462 Dint_increment(resultp1,resultp2);
464 break;
465 case ROUNDMINUS:
466 if (Dbl_isone_sign(srcp1)) {
467 Dint_decrement(resultp1,resultp2);
469 break;
470 case ROUNDNEAREST:
471 if (src_exponent == -1)
472 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
473 if (Dbl_iszero_sign(srcp1)) {
474 Dint_increment(resultp1,resultp2);
476 else {
477 Dint_decrement(resultp1,resultp2);
482 Dint_copytoptr(resultp1,resultp2,dstptr);
483 if (inexact) {
484 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
485 else Set_inexactflag();
487 return(NOEXCEPTION);