1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4 *
5 * Floating-point emulation code
6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7 */
8/*
9 * BEGIN_DESC
10 *
11 * File:
12 * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $
13 *
14 * Purpose:
15 * Floating-point to Unsigned Fixed-point Converts
16 *
17 * External Interfaces:
18 * dbl_to_dbl_fcnvfu(srcptr,_nullptr,dstptr,status)
19 * dbl_to_sgl_fcnvfu(srcptr,_nullptr,dstptr,status)
20 * sgl_to_dbl_fcnvfu(srcptr,_nullptr,dstptr,status)
21 * sgl_to_sgl_fcnvfu(srcptr,_nullptr,dstptr,status)
22 *
23 * Internal Interfaces:
24 *
25 * Theory:
26 * <<please update with a overview of the operation of this file>>
27 *
28 * END_DESC
29*/
30
31
32#include "float.h"
33#include "sgl_float.h"
34#include "dbl_float.h"
35#include "cnv_float.h"
36
37/************************************************************************
38 * Floating-point to Unsigned Fixed-point Converts *
39 ************************************************************************/
40
41/*
42 * Single Floating-point to Single Unsigned Fixed
43 */
44/*ARGSUSED*/
45int
46sgl_to_sgl_fcnvfu(
47 sgl_floating_point *srcptr,
48 unsigned int *_nullptr,
49 unsigned int *dstptr,
50 unsigned int *status)
51{
52 register unsigned int src, result;
53 register int src_exponent;
54 register boolean inexact = FALSE;
55
56 src = *srcptr;
57 src_exponent = Sgl_exponent(src) - SGL_BIAS;
58
59 /*
60 * Test for overflow
61 */
62 if (src_exponent > SGL_FX_MAX_EXP + 1) {
63 if (Sgl_isone_sign(src)) {
64 result = 0;
65 } else {
66 result = 0xffffffff;
67 }
68 if (Is_invalidtrap_enabled()) {
69 return(INVALIDEXCEPTION);
70 }
71 Set_invalidflag();
72 *dstptr = result;
73 return(NOEXCEPTION);
74 }
75 /*
76 * Generate result
77 */
78 if (src_exponent >= 0) {
79 /*
80 * Check sign.
81 * If negative, trap unimplemented.
82 */
83 if (Sgl_isone_sign(src)) {
84 result = 0;
85 if (Is_invalidtrap_enabled()) {
86 return(INVALIDEXCEPTION);
87 }
88 Set_invalidflag();
89 *dstptr = result;
90 return(NOEXCEPTION);
91 }
92 Sgl_clear_signexponent_set_hidden(src);
93 Suint_from_sgl_mantissa(src,src_exponent,result);
94
95 /* check for inexact */
96 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
97 inexact = TRUE;
98 /* round result */
99 switch (Rounding_mode()) {
100 case ROUNDPLUS:
101 result++;
102 break;
103 case ROUNDMINUS: /* never negative */
104 break;
105 case ROUNDNEAREST:
106 if (Sgl_isone_roundbit(src,src_exponent) &&
107 (Sgl_isone_stickybit(src,src_exponent) ||
108 (result & 1))) {
109 result++;
110 }
111 break;
112 }
113 }
114 } else {
115 result = 0;
116
117 /* check for inexact */
118 if (Sgl_isnotzero_exponentmantissa(src)) {
119 inexact = TRUE;
120 /* round result */
121 switch (Rounding_mode()) {
122 case ROUNDPLUS:
123 if (Sgl_iszero_sign(src)) {
124 result++;
125 }
126 break;
127 case ROUNDMINUS:
128 if (Sgl_isone_sign(src)) {
129 result = 0;
130 if (Is_invalidtrap_enabled()) {
131 return(INVALIDEXCEPTION);
132 }
133 Set_invalidflag();
134 inexact = FALSE;
135 }
136 break;
137 case ROUNDNEAREST:
138 if (src_exponent == -1 &&
139 Sgl_isnotzero_mantissa(src)) {
140 if (Sgl_isone_sign(src)) {
141 result = 0;
142 if (Is_invalidtrap_enabled()) {
143 return(INVALIDEXCEPTION);
144 }
145 Set_invalidflag();
146 inexact = FALSE;
147 }
148 else result++;
149 }
150 break;
151 }
152 }
153 }
154 *dstptr = result;
155 if (inexact) {
156 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
157 else Set_inexactflag();
158 }
159 return(NOEXCEPTION);
160}
161
162/*
163 * Single Floating-point to Double Unsigned Fixed
164 */
165/*ARGSUSED*/
166int
167sgl_to_dbl_fcnvfu(
168 sgl_floating_point *srcptr,
169 unsigned int *_nullptr,
170 dbl_unsigned *dstptr,
171 unsigned int *status)
172{
173 register int src_exponent;
174 register unsigned int src, resultp1, resultp2;
175 register boolean inexact = FALSE;
176
177 src = *srcptr;
178 src_exponent = Sgl_exponent(src) - SGL_BIAS;
179
180 /*
181 * Test for overflow
182 */
183 if (src_exponent > DBL_FX_MAX_EXP + 1) {
184 if (Sgl_isone_sign(src)) {
185 resultp1 = resultp2 = 0;
186 } else {
187 resultp1 = resultp2 = 0xffffffff;
188 }
189 if (Is_invalidtrap_enabled()) {
190 return(INVALIDEXCEPTION);
191 }
192 Set_invalidflag();
193 Duint_copytoptr(resultp1,resultp2,dstptr);
194 return(NOEXCEPTION);
195 }
196 /*
197 * Generate result
198 */
199 if (src_exponent >= 0) {
200 /*
201 * Check sign.
202 * If negative, trap unimplemented.
203 */
204 if (Sgl_isone_sign(src)) {
205 resultp1 = resultp2 = 0;
206 if (Is_invalidtrap_enabled()) {
207 return(INVALIDEXCEPTION);
208 }
209 Set_invalidflag();
210 Duint_copytoptr(resultp1,resultp2,dstptr);
211 return(NOEXCEPTION);
212 }
213 Sgl_clear_signexponent_set_hidden(src);
214 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
215
216 /* check for inexact */
217 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
218 inexact = TRUE;
219 /* round result */
220 switch (Rounding_mode()) {
221 case ROUNDPLUS:
222 Duint_increment(resultp1,resultp2);
223 break;
224 case ROUNDMINUS: /* never negative */
225 break;
226 case ROUNDNEAREST:
227 if (Sgl_isone_roundbit(src,src_exponent) &&
228 (Sgl_isone_stickybit(src,src_exponent) ||
229 Duint_isone_lowp2(resultp2))) {
230 Duint_increment(resultp1,resultp2);
231 }
232 break;
233 }
234 }
235 } else {
236 Duint_setzero(resultp1,resultp2);
237
238 /* check for inexact */
239 if (Sgl_isnotzero_exponentmantissa(src)) {
240 inexact = TRUE;
241 /* round result */
242 switch (Rounding_mode()) {
243 case ROUNDPLUS:
244 if (Sgl_iszero_sign(src)) {
245 Duint_increment(resultp1,resultp2);
246 }
247 break;
248 case ROUNDMINUS:
249 if (Sgl_isone_sign(src)) {
250 resultp1 = resultp2 = 0;
251 if (Is_invalidtrap_enabled()) {
252 return(INVALIDEXCEPTION);
253 }
254 Set_invalidflag();
255 inexact = FALSE;
256 }
257 break;
258 case ROUNDNEAREST:
259 if (src_exponent == -1 &&
260 Sgl_isnotzero_mantissa(src)) {
261 if (Sgl_isone_sign(src)) {
262 resultp1 = 0;
263 resultp2 = 0;
264 if (Is_invalidtrap_enabled()) {
265 return(INVALIDEXCEPTION);
266 }
267 Set_invalidflag();
268 inexact = FALSE;
269 }
270 else Duint_increment(resultp1,resultp2);
271 }
272 }
273 }
274 }
275 Duint_copytoptr(resultp1,resultp2,dstptr);
276 if (inexact) {
277 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
278 else Set_inexactflag();
279 }
280 return(NOEXCEPTION);
281}
282
283/*
284 * Double Floating-point to Single Unsigned Fixed
285 */
286/*ARGSUSED*/
287int
288dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *_nullptr,
289 unsigned int *dstptr, unsigned int *status)
290{
291 register unsigned int srcp1, srcp2, result;
292 register int src_exponent;
293 register boolean inexact = FALSE;
294
295 Dbl_copyfromptr(srcptr,srcp1,srcp2);
296 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
297
298 /*
299 * Test for overflow
300 */
301 if (src_exponent > SGL_FX_MAX_EXP + 1) {
302 if (Dbl_isone_sign(srcp1)) {
303 result = 0;
304 } else {
305 result = 0xffffffff;
306 }
307 if (Is_invalidtrap_enabled()) {
308 return(INVALIDEXCEPTION);
309 }
310 Set_invalidflag();
311 *dstptr = result;
312 return(NOEXCEPTION);
313 }
314 /*
315 * Generate result
316 */
317 if (src_exponent >= 0) {
318 /*
319 * Check sign.
320 * If negative, trap unimplemented.
321 */
322 if (Dbl_isone_sign(srcp1)) {
323 result = 0;
324 if (Is_invalidtrap_enabled()) {
325 return(INVALIDEXCEPTION);
326 }
327 Set_invalidflag();
328 *dstptr = result;
329 return(NOEXCEPTION);
330 }
331 Dbl_clear_signexponent_set_hidden(srcp1);
332 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
333
334 /* check for inexact */
335 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
336 inexact = TRUE;
337 /* round result */
338 switch (Rounding_mode()) {
339 case ROUNDPLUS:
340 result++;
341 break;
342 case ROUNDMINUS: /* never negative */
343 break;
344 case ROUNDNEAREST:
345 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
346 (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
347 result&1))
348 result++;
349 break;
350 }
351 /* check for overflow */
352 if (result == 0) {
353 result = 0xffffffff;
354 if (Is_invalidtrap_enabled()) {
355 return(INVALIDEXCEPTION);
356 }
357 Set_invalidflag();
358 *dstptr = result;
359 return(NOEXCEPTION);
360 }
361 }
362 } else {
363 result = 0;
364
365 /* check for inexact */
366 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
367 inexact = TRUE;
368 /* round result */
369 switch (Rounding_mode()) {
370 case ROUNDPLUS:
371 if (Dbl_iszero_sign(srcp1)) result++;
372 break;
373 case ROUNDMINUS:
374 if (Dbl_isone_sign(srcp1)) {
375 result = 0;
376 if (Is_invalidtrap_enabled()) {
377 return(INVALIDEXCEPTION);
378 }
379 Set_invalidflag();
380 inexact = FALSE;
381 }
382 break;
383 case ROUNDNEAREST:
384 if (src_exponent == -1 &&
385 Dbl_isnotzero_mantissa(srcp1,srcp2))
386 if (Dbl_isone_sign(srcp1)) {
387 result = 0;
388 if (Is_invalidtrap_enabled()) {
389 return(INVALIDEXCEPTION);
390 }
391 Set_invalidflag();
392 inexact = FALSE;
393 }
394 else result++;
395 }
396 }
397 }
398 *dstptr = result;
399 if (inexact) {
400 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
401 else Set_inexactflag();
402 }
403 return(NOEXCEPTION);
404}
405
406/*
407 * Double Floating-point to Double Unsigned Fixed
408 */
409/*ARGSUSED*/
410int
411dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *_nullptr,
412 dbl_unsigned * dstptr, unsigned int *status)
413{
414 register int src_exponent;
415 register unsigned int srcp1, srcp2, resultp1, resultp2;
416 register boolean inexact = FALSE;
417
418 Dbl_copyfromptr(srcptr,srcp1,srcp2);
419 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
420
421 /*
422 * Test for overflow
423 */
424 if (src_exponent > DBL_FX_MAX_EXP + 1) {
425 if (Dbl_isone_sign(srcp1)) {
426 resultp1 = resultp2 = 0;
427 } else {
428 resultp1 = resultp2 = 0xffffffff;
429 }
430 if (Is_invalidtrap_enabled()) {
431 return(INVALIDEXCEPTION);
432 }
433 Set_invalidflag();
434 Duint_copytoptr(resultp1,resultp2,dstptr);
435 return(NOEXCEPTION);
436 }
437
438 /*
439 * Generate result
440 */
441 if (src_exponent >= 0) {
442 /*
443 * Check sign.
444 * If negative, trap unimplemented.
445 */
446 if (Dbl_isone_sign(srcp1)) {
447 resultp1 = resultp2 = 0;
448 if (Is_invalidtrap_enabled()) {
449 return(INVALIDEXCEPTION);
450 }
451 Set_invalidflag();
452 Duint_copytoptr(resultp1,resultp2,dstptr);
453 return(NOEXCEPTION);
454 }
455 Dbl_clear_signexponent_set_hidden(srcp1);
456 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
457 resultp2);
458
459 /* check for inexact */
460 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
461 inexact = TRUE;
462 /* round result */
463 switch (Rounding_mode()) {
464 case ROUNDPLUS:
465 Duint_increment(resultp1,resultp2);
466 break;
467 case ROUNDMINUS: /* never negative */
468 break;
469 case ROUNDNEAREST:
470 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
471 if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
472 Duint_isone_lowp2(resultp2))
473 Duint_increment(resultp1,resultp2);
474 }
475 }
476 } else {
477 Duint_setzero(resultp1,resultp2);
478
479 /* check for inexact */
480 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
481 inexact = TRUE;
482 /* round result */
483 switch (Rounding_mode()) {
484 case ROUNDPLUS:
485 if (Dbl_iszero_sign(srcp1)) {
486 Duint_increment(resultp1,resultp2);
487 }
488 break;
489 case ROUNDMINUS:
490 if (Dbl_isone_sign(srcp1)) {
491 resultp1 = resultp2 = 0;
492 if (Is_invalidtrap_enabled()) {
493 return(INVALIDEXCEPTION);
494 }
495 Set_invalidflag();
496 inexact = FALSE;
497 }
498 break;
499 case ROUNDNEAREST:
500 if (src_exponent == -1 &&
501 Dbl_isnotzero_mantissa(srcp1,srcp2))
502 if (Dbl_iszero_sign(srcp1)) {
503 Duint_increment(resultp1,resultp2);
504 } else {
505 resultp1 = 0;
506 resultp2 = 0;
507 if (Is_invalidtrap_enabled()) {
508 return(INVALIDEXCEPTION);
509 }
510 Set_invalidflag();
511 inexact = FALSE;
512 }
513 }
514 }
515 }
516 Duint_copytoptr(resultp1,resultp2,dstptr);
517 if (inexact) {
518 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
519 else Set_inexactflag();
520 }
521 return(NOEXCEPTION);
522}
523
524

source code of linux/arch/parisc/math-emu/fcnvfu.c